I have a serious problem (with code, that is)...
I have a page with a TabStrip control on it. Using the Selected option on the first tab (set to true) I can't get that tab to be the active tab when the page loads. After load, clicking on any tab but the first one makes the tab LOOK like it is selected, but the content doesn't change for any tab until I click on that first tab. In other words, I can't set the active tab using the HTML Helper - with or without the Selected property being set, the tabstrip just doesn't work until I click the first tab.
What I'm trying to do is this: tab 1 has a data grid and tabs 2-4 have charts. When initially loaded, the grid is displayed. When one of the other tabs are selected I want to capture that and check the number of categories in the chart. If there are more than the current window size can handle, I want to manually set the width property of the chart and call the resize method so the user scrolls horizontally (without doing this, there are some charts where the category names look like an ink blot - one in particular can have 387 categories - ick, but what the client wants).
At this point I am not even sure if this will work. But I know the client will pitch a fit if I can't get that first tab automatically selected when the page loads. The next fit comes when I can't get the chart resized so it is readable. FYI, Bootstrap 5's native tabs work but the Kendo TabStrip does not. If I can't get this working, I will have to go back to that approach to see if I can get the chart to resize.
And FYI, this particular page is not wrapped in any Bootstrap containers, just nested in an Accordian control.
Dear All.
I have a listview within the listview items are displayed. This is my current code for the html.
<
section
>
<
script
type
=
"text/x-kendo-tmpl"
id
=
"templateRC"
>
<
div
id
=
"selectedRC"
class
=
" SetHeight"
>
<
span
>#:ID#</
span
>
</
div
>
</
script
>
<
div
class
=
"demo-section k-content wide"
>
@(Html.Kendo().ListView<
SLM.Models.ViewModel
>()
.Name("listView")
.TagName("div")
.ClientTemplateId("templateRC")
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("_Reports_Chart", "Home", new { iTypeID = Model.TYPE2_ID })
)
)
.Selectable(ListViewSelectionMode.Single)
// .Events(events => events.Change("onSelectReport"))
)
</
div
>
</
section
>
My css Code:
.SetHeight {
width: calc(50% - 3%);
border: 1px solid #008000;
margin: 1%;
float: left;
}
When I check my browser the items will displayed like rectangles, so theyre not equal width and height. I tried adding some javascript to get the width and use it for the height but it keeps displaying like a rectangle.
The Jquery:
$(
function
() {
var
divWidth = $(
'.SetHeight'
).width();
$(
'.SetHeight'
).height(divWidth);
console.log(divWidth);
});
(logging also returns null. When I create a custom project on codepen. it does work for some reason.)
So now is my question: What do I need to change/add/remove to make the boxes equal width and height(squares).
Kind regards. Bjorn
I was converting HtmlHelps to TagHelpers because the formatting in my code files is getting out of control. I realized that some Kendo controls are not that straightforward to convert.
This works fine:
@(Html.Kendo().TabStrip()
.Name("tabStrip1")
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items =>
{
items.Add().SpriteCssClasses("fa-duotone fa-clock-rotate-left").Text("History").Content(@<text>@Html.DisplayFor(m => m.History, "LetterHistory")</text>);
items.Add().SpriteCssClasses("fa-duotone fa-thumbs-up").Text("Approvers").Content(@<text>@Html.DisplayFor(m => m.Approvers, "LetterApprovers")</text>);
items.Add().SpriteCssClasses("fa-duotone fa-magnifying-glass").Text("Details").Content("");
items.Add().SpriteCssClasses("fa-duotone fa-link").Text("Attachments").Content(@<text>@await Component.InvokeAsync(viewName, new { LetterGuid = Model.IdCode.ToString() })</text>);
})
)
In TagHelper format, content is not shown for any tabs:
<kendo-tabstrip name="tabStrip">
<popup-animation>
<open effects="fade:in" />
</popup-animation>
<items>
<tabstrip-item text="History" icon-class="fa-duotone fa-clock-rotate-left" selected="true">
<content>@Html.DisplayFor(m => m.History, "LetterHistory")</content>
</tabstrip-item>
<tabstrip-item text="Approvers" icon-class="fa-duotone fa-thumbs-up">
<content></content>
</tabstrip-item>
<tabstrip-item text="Details" icon-class="fa-duotone fa-magnifying-glass">
<content>@Html.DisplayFor(m => m.Approvers, "LetterApprovers")</content>
</tabstrip-item>
<tabstrip-item text="Attachments" icon-class="fa-duotone fa-link">
<content>@await Component.InvokeAsync(viewName, new { LetterGuid = Model.IdCode.ToString() })</content>
</tabstrip-item>
</items>
</kendo-tabstrip>
I have the Upload control in an EditorTemplate as follows:
/Views/Letter/EditorTemplates/LetterAttachmentsManage.cshtml:
@using DACRL.Portal.ColorAdmin.Controllers
@using DACRL.Portal.ColorAdmin.Extensions
@model Guid?
@{
string[] extensions = { ".jpg", ".png", ".pdf", ".ppt", ".pptx", ".doc", ".docx", ".xls", ".xlsx" };
}
@Html.HiddenFor(m => m)
<kendo-upload name="letterFiles" multiple="true">
<async save-url="@Url.Action(nameof(UploadController.ChunkSave), ControllerExtensions.Nameof<UploadController>())"
remove-url="@Url.Action(nameof(UploadController.Remove), ControllerExtensions.Nameof<DashboardController>())"
auto-upload="true"
chunk-size="11000" />
<validation allowed-extensions="@extensions" max-file-size="36700160" />
</kendo-upload>
This template is placed within a form on a parent view as
/Views/Letter/Create.cshtml:
@model LetterModel
@using (Html.BeginForm("", "Letter", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(m => m.IdCode)
<div class="panel mt-20px" data-sortable-id="ui-widget-16">
<div class="panel-heading bg-da-blue text-white">
<h4 class="panel-title">RL Info</h4>
</div>
<div class="panel-body">
@Html.EditorFor(m => m, "Letter")
</div>
</div>
<div class="panel mt-20px" data-sortable-id="ui-widget-16">
<div class="panel-heading bg-da-blue text-white">
<h4 class="panel-title">Attachments</h4>
</div>
<div class="panel-body">
@Html.EditorFor(m => m.IdCode, "LetterAttachmentsManage")
</div>
</div>
<div class="row mt-3">
<div class="col-md-1">
<button type="submit" class="btn btn-primary w-100 me-5px" formaction="CreateSave" title="@(Model.IsUpdateCase ? "Update letter" : "Save letter")">@(Model.IsUpdateCase ? "Update" : "Save")</button>
</div>
<div class="col-md-1">
<button type="submit" class="btn btn-default w-100" formaction="CreateSubmit" title="@(Model.IsUpdateCase ? "Update letter & submit" : "Save letter & submit")">Submit</button>
</div>
</div>
}
I'm trying to handle the File logic separately so I have the Upload Controller:
public class UploadController : BaseControllerWithAuth<UploadController>
{
private readonly IWebHostEnvironment hostEnvironment;
public UploadController(IWebHostEnvironment hostingEnvironment, IHttpContextAccessor httpContextAccess, IUserService userService) : base(httpContextAccess, userService) => hostEnvironment = hostingEnvironment;
public async Task<ActionResult> ChunkSave([Bind(Prefix = "IdCode.letterFiles")] IEnumerable<IFormFile>? letterFiles, string? metaData, Guid? idCode)
{
try
{
if (metaData == null)
return await Save(letterFiles);
var chunkData = JsonSerializer.Deserialize<ChunkMetaDataModel>(metaData)!;
if (letterFiles != null)
{
foreach (var file in letterFiles) AppendToFile(Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath, chunkData!.FileName), file, idCode?.ToString());
}
var fileBlob = new FileResultModel
{
uploaded = chunkData!.TotalChunks - 1 <= chunkData.ChunkIndex,
fileUid = chunkData.UploadUid
};
return Json(fileBlob);
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(ChunkSave)}: Error: {ex.Message}");
throw;
}
}
public ActionResult Remove(string[]? fileNames)
{
try
{
if (fileNames == null) return Content("");
foreach (var fullName in fileNames)
{
var fileName = Path.GetFileName(fullName);
var physicalPath = Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath, fileName);
if (System.IO.File.Exists(physicalPath)) System.IO.File.Delete(physicalPath);
}
return Content("");
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(Remove)}: Error: {ex.Message}");
throw;
}
}
private void AppendToFile(string fullPath, IFormFile content, string? idCode)
{
try
{
var basePath = Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath);
if (!Directory.Exists(basePath)) Directory.CreateDirectory(basePath);
var letterPath = Path.Combine(basePath, idCode!);
if (!Directory.Exists(letterPath)) Directory.CreateDirectory(letterPath);
using var stream = new FileStream(fullPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
content.CopyTo(stream);
}
catch (IOException ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(AppendToFile)}: Error: {ex.Message}");
throw;
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(AppendToFile)}: Error: {ex.Message}");
throw;
}
}
private async Task<ActionResult> Save([Bind(Prefix = "IdCode.letterFiles")] IEnumerable<IFormFile>? letterFiles)
{
try
{
if (letterFiles == null) return Content("");
foreach (var file in letterFiles)
{
var fileContent = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
var fileName = Path.GetFileName(fileContent.FileName!.Trim('"'));
var physicalPath = Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath, fileName);
await using var fileStream = new FileStream(physicalPath, FileMode.Create);
await file.CopyToAsync(fileStream);
}
return Content("");
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(Save)}: Error: {ex.Message}");
throw;
}
}
}
Note: Due to this being an EditorTemplate, I had to add the
[Bind(Prefix = "IdCode.letterFiles")]
Now, once the file is being chunked back to the Controller's ChunkSave action, I need to get the value of the model of this EditorTemplate as it will correlate with the primary entity later.
I have tried adding a parameter to the Controller's ChunkSave action as Guid? idCode. But I always get a null there.
How do I go about this dilemma?
I'm not using Newtosoft.Json anymore so I tried to deserialize the metadata like this:
var chunkData = JsonSerializer.Deserialize<ChunkMetaDataModel>(metaData)!;
It's not getting de-serialized properly as all strings are null and all integers are 0s.
Please update this documentation page: ASP.NET Core Upload Component Chunk Upload | Telerik UI for ASP.NET Core & this demo: Chunk Upload in ASP.NET Core Upload Component Demo | Telerik UI for ASP.NET Core soon as I'm stuck for now.
I originally got help from StackOverflow from my question: c# - System.Text.Json.* & deserialization of streams - Stack Overflow
This question is two-fold, and I can't seem to find the answers in the documentation. For background info, I'm using the latest version of Wizard (the Tag version) :
TIA!
Hi All,
This example of a responsive form is not working. The columns never collapse and stack. They are aways 2 columns.
I have tried many other things also but nothing seems to work.
I am using TagHelpers FYI
Update: I also tried the TagHelpers sample and it does not work either.
Is it possible to get a Respond kendo-form that has 2, 3, or 4 columns in desktop but collapse to 1 column on mobile?
Thanks
Thanks
I'm using the Grid component (ASP.NET Core Razor Pages).
I would like a column that when clicked will navigate to a specified Page within my application, passing along with it one or more of the column values in my model.
Ideally I'd like to avoid Templates, because it just seems like a lot of string to manage to get an HTML output that I like.
I did come across Commands with a custom Click, but I haven't been able to find documentation yet that shows how I can pass the row details along so I can access specific column values to use in a redirect via JavaScript.
I did get this working with
columns.Template("my anchor tag html goes here with template syntax for #:SomePropValue#")
But it doesn't come across as "clean" as I'd like.
So I'm hoping there's some way to access/pass along a given row's column values in a custom click so I can just use JS for a redirect?
columns.Command(action => {action.Custom("View Application").Click("myJavaScriptFunction")
If there's also a way to do this by using only Html Helpers/Razor syntax, I'm also okay with that! But I couldn't find what I'm looking for with just that either, so I started looking into custom clicks and JS.
HI
The SelectListItemBuilder's HtmlAttributes property of DropDownList was gone, WHY ???
namespace Kendo.Mvc.UI.Fluent
{
 public class SelectListItemBuilder : IHideObjectMembers
 {
Everyone needs HtmlAttributes property.
*Kendo.Mvc, Version=2021.3.1207.0。
(telerik.ui.for.aspnet.core\2021.3.1207\lib\net6.0\Kendo.Mvc.dll)
Best regards
Chris
I have a PanelBar control with 3 panels, each holding a Chart control with column items. I am using the HtmlHelper build the charts. The PanelBar is in a container that spans 100% of the screen. By default, the charts in the panels render at about 25% of the width - and that means charts with a lot of categories are seriously compressed and unreadable.
I've tried using the Width option of ChartArea (inside Chart), and while that works, I can't always be sure the double I set this to will be right for all user's browsers. There is no string option, so Width has to be a number of pixels.
Using HtmlAttributes (adding style) also has no effect.
How can I get the charts to occupy 100% of the container other than just guessing using ChartArea's Width or resorting to JavaScript to redraw the chart after the page is rendered?