Kendo UI Conditional Button in ClientTemplate - asp.net-mvc

I'm trying to get a conditional client template to work in a Kendo Grid that will call into my controller with a simple userName string as a parameter but I cannot figure out the syntax to get this working correctly.
My template is in my view like this:
columns.Bound(user => user.IsLockedOut).ClientTemplate(
"# if (IsLockedOut == true) { #" +
"<input type='button' value='Unlock Acc' onclick='location.href=" + #Url.Action("UnlockAccount", "Administration", new { userName = "#= UserName #" + }) + "/>" +
"# } else { #" +
"Unlocked" +
"# } #"
);
And the action method of the controller looks like:
public void UnlockAccount(string userName)
{
}
At the moment the error generated is:
CS1525: Invalid expression term '}'
I've been looking at this for a couple of hours now and I cannot see the wood for the trees now.

You have some '+' plus symbol that you do not actually need. Also you do not need the 'at' sign # in front of the helper.
new { userName = "#= UserName #" + }) //<- that last plus

This method worked for me.
const string ShowUpdateButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-edit' href='\\#'><span class='k-icon k-edit'></span>Update</a>#}#";
const string ShowReverseButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-reverse' href='/JournalDetail/Reverse/#: ID #' ><span class='k-icon k-reverse'></span>Reverse</a>#}#";
const string ShowDeleteButton = "#if (IsAdjustment == true) {#<a class='k-button k-button-icontext k-grid-delete' href='\\#'><span class='k-icon k-delete'></span>Delete</a>#}#";
You can do the template inline but I find it easier (particularly for multiple buttons) if you declare constants and then use string.format to concatenate them.
col.Template(o => o).ClientTemplate(string.Format("{0}{1}{2}", ShowUpdateButton, ShowDeleteButton, ShowReverseButton));
The upside is it will work with popup editor whereas jquery hacks will ignore the conditional status when a user cancels out of edit. A cancel from the popup editor will restore the grid row from the viewmodel or wherever Kendo stores it which results in button states from before any jquery/javascript hack. The method above will also auto-wire the standard commands since I copied their HTML output for the client template.
The downside is that if Kendo changes their pattern for command buttons the client template may fail. I tired several other methods besides this one and the downside to this method seems better than the other methods.
Note on Kendo Forums: As of the date of this post, they do not appear to allow people who do not pay for support to post to the forums so I would suggest posting questions here instead. They monitor Stack Overflow and in my experience they seem to answer questions more quickly here.

I've gotta a bit further but only by manually writing the URL like this:
"<input type='button' value='Unlock Acc' onclick='location.href=/Administration/TryUnlockAccount?userName=#= UserName #'/>"
Still doesn't call my controller method though but it does have the right parameter value ...

Related

Checkboxes generated via CheckBoxFor helper turn into type=hidden because of MaterializeCSS

I'm creating a website with ASP.NET MVC5 and I'm using MaterializeCSS for the first time, which looks like a very exciting framework.
However, the checkboxes generated by CheckBoxFor helper become hidden !
When I write :
#Html.CheckBoxFor(m => m.IsAgreeTerms)
The generated HTML is :
<input name="IsAgreeTerms" type="hidden" value="false">
Why does Materialize change my type=checkbox into type=hidden ?
I tried to add type="checkbox" in the CheckboxFor helper, but it doesnt change anything. The only way is to modify in in my browser's console.
The only solution I found is this SO thread.
However, the accepted answer doesn't change anything for me.
The other answer works, but I think it's ugly to add some JS script to modify what Materialize modifies without my consent.
Is there any way to say "Hey, I ask for a type=checkbox, so just let my type=checkbox in the generated HTML" ?
Thank you
UPDATE :
My full ASP.NET MVC code is :
#Html.CheckBoxFor(m => m.IsAgreeTerms, new { #type = "checkbox" })
#Html.LabelFor(m => m.IsAgreeTerms, new { #class = "login-label" })
The full generated HTML is
<input data-val="true" data-val-required="Le champ IsAgreeTerms est requis." id="IsAgreeTerms" name="IsAgreeTerms" type="checkbox" value="true"
<input name="IsAgreeTerms" type="hidden" value="false">
<label class="login-label" for="IsAgreeTerms">IsAgreeTerms</label>
Here's a solution in the form of a html helper. It constructs a checkbox and label in the correct order:
public static IHtmlString CheckBoxWithLabelFor<TModel>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, bool>> expression,
string labelText,
object htmlAttributes = null
)
{
if (expression == null)
{
throw new ArgumentNullException(nameof(expression));
}
var checkBoxWithHidden = htmlHelper.CheckBoxFor(expression, htmlAttributes).ToHtmlString().Trim();
var pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1, StringComparison.Ordinal));
var labelHtml = htmlHelper.LabelFor(expression, labelText).ToHtmlString().Trim();
var result = pureCheckBox + Environment.NewLine + labelHtml + Environment.NewLine + $"<input type=\"hidden\" name=\"{ExpressionHelper.GetExpressionText(expression)}\" value=\"false\" />";
return new MvcHtmlString(result);
}
Is there other html generated by materialize.css? I think this happens because it is not possible apply a custom CSS to element input of type checkbox.
So, the checkbox becomes hidden and other html component represents visually the checkbox. Many components work like that.
UPDATE:
Why is Html checkbox generating an additional hidden input
OP here. Problem looks like more complex.
Actually, when using #Html.CheckBoxFor, MVC5 generates 3 fields, in that order :
Your input, with type="checkbox", binded to your model property
An hidden field (see the Claudio's link for an explaination)
Your label, generated by #Html.LabelFor
Problem is Materialize expects that in another order to work.
In your browser's console, just move the <label> element between the input and the hidden field, and everything works fine !
I found this very useful link, where, basically, it is said that the order of the generated fields by #Html.checkBoxFor will change ... In MVC6 !
As I'm working with MVC5, I use this very ugly solution in my _Layout:
$(":checkbox").each(function () {
$(this).nextAll("label").before($(this))
})
If anyone has a better idea, please feel free to post an elegant solution.

How to insert '_' as htmlAttributes in razor?

This is probably a simple question, but to which I havent found an answer yet.
How to escape the ' _ ' when creating an HtmlElement in razor?
To render a '-' in the final Html we put an ' _ ', but to render an '_' (underscore), How do we escape it? I tryed '#:', but it didn't work, and didn't find any other options...
Example:
#Html.CheckBox("Access_Groups", false, new
{
#class = "input-control checkbox",
#data_group = "I', looking for data-group",
#Description_pt = "<----- I'm looking for Description_pt"
})
#data_group will render as data-group as expected, but...
#Description_pt will render as Description-pt, and that is not what is expected (don't know how to escape the _ for this)
thank you
If you look at the signature of Html.Checkbox, we can see that it takes an object for the htmlAttributes. Further, looking at the syntax, its actually a key based collection of objects. A Dictionary<string,object> fits that bill and allows you to absolutely specify the name of the html attributes that you want to add (note each key is typed exactly how we want it to display).
#Html.CheckBox("Access_Groups", false, new Dictionary<string,object>
{{"class", "input-control checkbox"},
{"data-group", "I', looking for data-group"},
{"Description_pt", "SomeValue"}})
This renders the following HTML
<input Description_pt="SomeValue" class="input-control checkbox"
data-group="I', looking for data-group" id="Access_Groups"
name="Access_Groups" type="checkbox" value="true" />
Have you tried the HTML character code for underscore, i.e., _?

Kendo UI Grid in MVC with Conditional Custom Command Button

I have a KendoUI Grid I'm using an MVC web application, all working fine however I want to add a custom command button that is shown conditionally in the UI and simply executes a command on my controller passing it the required parameter.
columns.Command(command => command.Custom("UnlockAccount").SendDataKeys(true).Click())
The command is specified as above but I only want the button to show when the DataItems IsLocked property is true.
I also cannot figure out how to just call and method on the controller rather. I cannot find a demo of this on the Kendo site and not sure how to move this forward.
Here is a specific example for using client templates for conditional command buttons.
const string ShowUpdateButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-edit' href='\\#'><span class='k-icon k-edit'></span>Update</a>#}#";
const string ShowReverseButton = "#if (IsNetReversal == false) {#<a class='k-button k-button-icontext k-grid-reverse' href='/JournalDetail/Reverse/#: ID #' ><span class='k-icon k-reverse'></span>Reverse</a>#}#";
const string ShowDeleteButton = "#if (IsAdjustment == true) {#<a class='k-button k-button-icontext k-grid-delete' href='\\#'><span class='k-icon k-delete'></span>Delete</a>#}#";
You can do the template inline but I find it easier (particularly for multiple buttons) if you declare constants and then use string.format to concatenate them.
col.Template(o => o).ClientTemplate(string.Format("{0}{1}{2}", ShowUpdateButton, ShowDeleteButton, ShowReverseButton));
The upside is it will work with popup editor whereas jquery hacks will ignore the conditional status when a user cancels out of edit. A cancel from the popup editor will restore the grid row from the viewmodel or wherever Kendo stores it which results in button states from before any jquery/javascript hack. The method above will also auto-wire the standard commands since I copied their HTML output for the client template.
The downside is that if Kendo changes their pattern for command buttons the client template may fail. I tired several other methods besides this one and the downside to this method seems better than the other methods.
Note on Kendo Forums: As of the date of this post, they do not appear to allow people who do not pay for support to post to the forums so I would suggest posting questions here instead. They monitor Stack Overflow and in my experience they seem to answer questions more quickly here.
Use template column instead - via the ClientTemplate method.
Conditional templates are covered here and multiple times on the forums - the Command columns is not that flexible.
As of the December 2018 release of Kendo, you can now conditionally display custom buttons more easily, but it still relies on JavaScript to do its work, this function should be defined before your dataGrid or you'll run into issues.
function showCommand(dataItem) {
console.log("determining to hide or show" + dataItem);
// show the Edit button for the item with Status='New'
if (dataItem.Status == 'New') {
return true;
}
else {
return false;
}
}
Then the code for the Grid.
.Columns (columns => {
columns.Command (
command => command.Custom ("Approve")
.Visible ("showCommand")
.Click ("approveFunc")
)
.Width (100)
.HeaderTemplate ("Actions")
})
You can control custom command button visibility by Visible property.
columns.Command(command => command.Custom("UnlockAccount").SendDataKeys(true).Click().Visible("unlockAccountVisible"))
Visible property accepts JS function name and passes current dataItem as an argument.
JS function that evaluates button visibility:
<script>
function unlockAccountVisible(dataItem) {
// show the UnlockAccount button only when data item property IsLocked == true
return dataItem.IsLocked;
}
</script>
Read more in Show Command Buttons Conditionally kendo-ui documentation article.

Remove Blank Entry on DropDownList in MVC

I have been looking but couldn't find any way to remove the blank item on my dropdown list. Ideally, I would like to do this without altering the model. I just want to remove the blank item from the dropdown list so that users are forced to select one (so they can't select "blank").
Note: I am using the default dropdown list that comes with the MVC framework.
Here is my code:
' controller action:
ViewBag.CompanyId = New SelectList(db.Companies, "CompanyId", "Name")
' view:
#Html.DropDownList("CompanyId", String.Empty)
#Html.ValidationMessageFor(Function(model) model.CompanyId)
How are you building the options for your dropdown?
I never have blank options.
I usually create my dropdown like this:
#Html.DropDownListFor(x=>x.Client, new SelectList(Model.Clients))
Obviously your model options will be different.
Answer: Remove String.Empty
Update on 2021: My problem was on the JS script side, I was appending an empty line within my dropdown :D
Like this:
$("#" + "YourID").append('<option></option>'); //Remove This Line
for (var i = 0; i < CountriesList.length; i++)
{
$("#" + "YourID").append('<option value="' + CountriesList[i] + '">' + CountriesList[i] + '</option>');
}
Removing the first line will get you directly the first element from your Items list :)
Happy coding everyone.

Passing NewLine (or <Br />) inside ViewData["msg"]

How do I pass an Environment.NewLine (or a < br />) inside a ViewData["msg"]
that renders as a real <br /> inside the View itself?
I'm using C# ...
You can simply use
HttpUtility.HtmlEncode("<br />");
Have a look here for further details.
EDIT:
I am sorry but I did not understand the question at the beginning. I thought you wanted to encode the passed string. Sometimes I read question too fast :)
Anyway to completely answer your question have a look at these samples. Suppose in your action you have:
[HttpGet]
public virtual ActionResult Index() {
ViewData["Message"] = "This is a test." + "<br />" + "Does it work?";
return View();
}
And in your view you have
<p>Sample 1: <br /><%= ViewData["Message"]%></p>
<p>Sample 2: <br /><%: ViewData["Message"]%></p>
Notice the difference between the two construct. You will get the following results:
Sample 1:
This is a test.
Does it work?
Sample 2:
This is a test.<br />Does it work?
So the first sample usage answer your question. The key is to simply not encoding the string as opposed to what I understood at the beginning. The second construct, the one that use <%: %>, available if you're using .NET 4.0, automatically encode every string it render.
If you still want to use this latest construct and avoid that the string would be encoded you have to use a trick. Simply tell the construct that the string is already encoded and it does not need to be re-encoded. To achieve this use this sample code
[HttpGet]
public virtual ActionResult Index() {
ViewData["Message2"] = MvcHtmlString.Create( "This is a test." + "<br />" + "Does it work?" );
return View();
}
and in the view normally use the <%: %> construct
<p>Sample 3: <br /><%: ViewData["Message2"]%></p>
For more details on using the MvcHtmlString and how it works please refer to this question on SO.
Ciao!
Did you try \n or \r inside the ViewData string itself?
Use this:
TempData["MsgString"] = MvcHtmlString.Create("No Data" + "<br />" + "For Something");
Or, with variables:
TempData["MsgString"] = MvcHtmlString.Create(Strings.StrNoData + "<br />" + Strings.StrSomething);

Resources