Can I add conditions within Kendo().DropDownList() definition? - kendo-ui

I have a kendo dropdownlist and want to add a property to it but only if some condition is met. It that possible and, if so, what is the syntax? Below is the concept that I have in mind.
#(Html.Kendo().DropDownList()
.Name("My Dropdown List")
.Value(Model.xxx)
If (some condition){
.Height(1000)
}
.DataTextField("MYDESCRIPTIEN")
.DataValueField("MYFIELD")
.HtmlAttributes(new { style = "width:300px" })
)

Update: With regard to the Height, I am afraid you are out of luck, as the Height() method expects a non-null integer value that will be always serialized to the client. The only option is to use two different widget declarations inside an external conditional statement.
===
Each fluent method expects a value of a certain type, or an expression that returns a value of this type. In addition, each configuration setting has a default value.
So you have a couple of options:
use a ternary operator that returns different values, depending on the condition. In one case it may return the property's default value
use an auxiliary variable, that is assigned the appropriate value in advance
Fluent methods that expect an action can be managed differently and you can use standard conditional statements, instead of ternaries.
Here is an example for all above scenarios:
#{
bool myCondition = false;
}
#(Html.Kendo().DropDownList()
.HtmlAttributes(myCondition ? new { style = "width: 100%" } : new object { /* empty object */ } )
.Events(e => {
if (myCondition)
{
// nothing here this time
}
else
{
e.DataBound("onDataBound");
}
})
)
<script>
function onDataBound(e) {
console.log("dataBound");
}
</script>

Hi there you should be able to add Events like so:
#(Html.Kendo().DropDownList()
.Name("My Dropdown List")
.Value(Model.xxx)
.DataTextField("MYDESCRIPTIEN")
.DataValueField("MYFIELD")
.HtmlAttributes(new { style = "width:300px" })
.Events(e => e.Change("OnDropDownChanged"));
)
JAVASCRIPT
function OnDropDownChanged(e)
{
//Do stuff to meet condition
}

Related

Function.bind used in event binding will always re-render because it is not pure

Working on render performance on React, wonder what is the best way to tackle this performance issue. (The code is overly simplified for clarity)
var TodoList = React.createClass({
getInitialState: function () {
return { todos: Immutable.List(['Buy milk', 'Buy eggs']) };
},
onTodoChange: function (index, newValue) {
this.setState({
todos: this.state.todos.set(index, newValue)
});
},
render: function () {
return (
this.state.todos.map((todo, index) =>
<TodoItem
value={todo}
onChange={this.onTodoChange.bind(null, index)} />
)
);
}
});
Assume only one single todo item has been changed. First, TodoList.render() will be called and start re-render the list again. Since TodoItem.onChange is binding to a event handler thru bind, thus, TodoItem.onChange will have a new value every time TodoList.render() is called. That means, even though we applied React.addons.PureRenderMixin to TodoItem.mixins, not one but all TodoItem will be re-rendered even when their value has not been changed.
I believe there are multiple ways to solve this, I am looking for an elegant way to solve the issue.
When looping through UI components in React, you need to use the key property. This allows for like-for-like comparisons. You will probably have seen the following warning in the console.
Warning: Each child in an array or iterator should have a unique "key" prop.
It's tempting to use the index property as the key, and if the list is static this may be a good choice (if only to get rid of the warning). However if the list is dynamic, you need a better key. In this case, I'd opt for the value of the todo item itself.
render: function () {
return (
this.state.todos.map((todo, index) => (
<TodoItem
key={todo}
value={todo}
onChange={this.onTodoChange.bind(null, index)}
/>
))
);
}
Finally, I think your conjecture about the nature of the onChange property is off the mark. Yes it will be a different property each time it is rendered. But the property itself has no rendering effect, so it doesn't come into play in the virtual DOM comparison.
UPDATE
(This answer has been updated based on the conversation below.)
Whilst it's true that a change to a non-render based prop like onChange won't trigger a re-render, it will trigger a virtual DOM comparison. Depending on the size of your app, this may be expensive or it may be trivial.
Should it be necessary to avoid this comparison, you'll need to implement the component's shouldComponentUpdate method to ignore any changes to non-render based props. e.g.
shouldComponentUpdate(nextProps) {
const ignoreProps = [ 'onChange' ];
const keys = Object.keys(this.props)
.filter((k) => ignoreProps.indexOf(k) === -1);
const keysNext = Object.keys(nextProps)
.filter((k) => ignoreProps.indexOf(k) === -1);
return keysNext.length !== keys.length ||
keysNext.some((k) => nextProps[k] !== this.props[k]);
}
If using state, you'll also need to compare nextState to this.state.

Kendo UI ComboBox DataSource RequestEnd event

I have a set of ComboBoxes whose items come from the same DataSource.Read event. In certain cases, I want to filter the items. My ComboBox looks like this:
#(Html.Kendo().ComboBox()
.HtmlAttributes(new { style = "font-size:10px; background-color: #f4f4f4;" })
.Name(string.Format( "{0}{1}", p, f[0] ) )
.Placeholder("Choose a value...")
.DataTextField("Name")
.DataValueField("Value")
.DataSource( source =>
{
source.Read( read => read.Action( "MyMethod", "MyController", new { _type = f[2] } ) )
.Events( e => e.RequestEnd( f[0] == "F1" && p != "P1" ? "SetFilter" : "NoFilter" ) );
} )
)
The variables, p, and f[x] are strings from a couple of foreach loops that I am running. As I run through those loops, my intention is to leave the DataSources alone except in the cases where f[0] == "F1" and p != "P1".
My two functions look like this:
function NoFilter() { }
function SetFilter( e ) {
var $filter = new Array();
$filter.push({ field: "Name", operator: "startswith", value: "O" });
e.sender.filter({ logic: "or", filters: $filter });
}
Altogether, I have twelve combo boxes that I am loading, of which two fit my exceptions. When the editor comes up, all the combo boxes briefly show wait indicators while they load. This all works well, except that the wait indicators for my two exceptions never go away, even though the filters are applied as I wish.
What am I missing that is leaving the wait indicators running?
Seems like you are recursively calling the server since you are setting a filter after reading the data. Setting a filter to the datasource will call the read method with the filter again. That means it will call the RequestEnd method again (Never ending).
Instead doing this way try to set the filter after the creation of the grid.

How to check if one list menu have a value greater than zero in jquery form validation?

I have more select menus, named menu1, menu2, menu3 etc...
All of them have values from 0 to 10. By default all are on 0.
How do I check with jquery validation plugin that at least one of the menus have a greater than zero value? Because each has a different name (I can give same class, but I do not see how this helps in validation plugin, because I can validate rules against form names not classes).
One solution is to create a custom rule.
I have adapted this answer and added a custom rule called mulitselect. This adds an error to the first dropdown list if none have a value > 0. Check the demo on jsfiddle.
note1 This currently is applied to every select list in the form, change the selector to limit it to certain select lists by class or otherwise.
note2 I added the onclick function after an invalid form has been submitted as adding it in the options resulted in validation that was a little too 'eager'.
js is as follows
$(function () {
$.validator.addMethod("multiselect", function (value, element) {
var countValid = $('select').filter(function () {
return $(this).val() > 0;
}).length;
if (countValid === 0 && $('select:first')[0] === element) {
return false;
}
else {
return true;
}
}, "please select at least one of the menus");
$('select').addClass("multiselect");
$('form').bind("invalid-form", function () {
$('form').validate().settings.onclick = function () { $("form").valid() };
}).validate({
debug: true
});
});

MVC 3 Bind Model property to 2 fields (e.g. Other Title)

I'm trying to achieve a very common scenario whereas given a list of options to choose from, the last one says "Other" and when selected the user is presented with the input field to specify what "other" is.
In my case, it's a list of Person's titles:
public List<string> TitleList
{
get
{
return new List<string> { "Mr", "Mrs", "Miss", "Dr", "Other" };
}
}
and what I'm trying to do is this:
#Html.DropDownListFor(m => m.Title, new SelectList(Model.TitleList), "Please select...") #Html.TextBoxFor(m => m.Title)
I want the model to bind the TextBox value when "Other" is selected in the DropDownLis, and bind to selected item in DropDownList in all other cases.
Is this achievable without adding an extra property on the Model?
a better solution is not to bind to two fields, instead, copy selected item from a drop-down into bound textbox with some clever javascript:
#Html.DropDownList("ddlTitle", new SelectList(Model.TitleList), "Please select")
#Html.TextBoxFor(m => m.Title, new { maxLength = 10 })
Javascript:
ToggleTitleFields = function () {
var title, txtTitle;
title = $('select#ddlTitle').val();
txtTitle = $('input#Title');
if (title === "Other") {
txtTitle.val("");
txtTitle.show();
return txtTitle.focus();
} else {
txtTitle.hide();
txtTitle.val(title);
return $('span[data-valmsg-for="Title"]').empty();
}
};
$(document).on("change", "select#ddlTitle", function(e) {
return ToggleTitleFields();
});
hope this helps somebody
found a client-side solution: add/remove the "name" attribute from DropDownList. Here's my coffee script:
ToggleTitleFields = () ->
if $('select#Title').val() == "Other"
$('select#Title').removeAttr('name')
else
$('select#Title').attr('name','Title')
Tsar,
Being honest, this isn't a scenario that I've had to deal with before, but is nonetheless a good one. If I were faced with this dilemma and was allowed to use a javascript solution, i'd present a previously 'hidden' textbox when other was chosen. The user would then have to enter the new value into this texbox, which on loosing focus would populate the selectlist and be selected. Then when the form was submitted, you'd have this new value still as part of the exisiting model.
Of course, you could also do a similar logic of showing the textbox when selecting other but this time, do a little logic on the httpost controller action to determine if the 'other' item was selected and then populate the model from the 'textbox' value.
Of course, both scenarios would need a heap of validation, but in principle, either approach would 'work'

Knockout checked binding issue

I'm having a problem with checkbox bindings not quite working with KnockoutJS 2.0. I have an array of objects. One of the properties of those objects is an array of different objects. In the child objects there are a few properties, one of which is a boolean. I build a list for each parent object and under each parent I show the children. For each list of children I have two views, a read only and an edit view. In the read only I have images that represent whether or not the item is checked based on the boolean property. This works and if I update the boolean value through the console, I'm seeing what I would expect--the image goes away or displays based on the value I assign. In the edit view, the images are replaced with a checkbox. I see the same behavior when I update the value through the console--it is checked when I expect it to be and not when I don't. The problem comes in when I check or uncheck the checkbox. Doing this doesn't change the underlying value the checkbox is bound to.
Here's the basic idea of my data.
[
{
"xxx": "yyy",
"xxx": "yyy",
...
"Displays": [
{
"xxx": "yyy",
...
"Excluded": false,
},
{
"xxx": "yyy",
...
"Excluded": true,
}
],
}
]
Here's the binding
<input type="checkbox" data-bind="checked: !Excluded()" />
the problem is that "checked" here is a bidirectional binding: the bound property needs to be read to generate the correct view, but needs also to be updated when you click on the checkbox. Contrast this to a binding like:
<span data-bind="text: 'your name is ' + name()"></span>
when the expression is only read, so you can use an expression (and you need to unwrap the observable).
So, you need to bind directly to the observable property, without "unwrapping" it adding '()', it will be done by knockout when needed, both for read and write:
<input type="checkbox" data-bind="checked: Excluded" />
See http://jsfiddle.net/saurus/usKwA/ for a simple example. Note how the checkbox labels are updated on change, showing that the model is updated and the rendering triggers correctly.
If you need to negate the value (so that the checkbox is checked when the value is false), you can add a writeable computed observable, as explained on http://knockoutjs.com/documentation/computedObservables.html section "Writeable computed observables", or you can negate the data in the viewmodel, doing it on the server just before sending the data, or on the client before populating the viewmodel.
hope this helps.
I know my answer is a bit late to the game here, but I had this problem today and this was the closest thread I could find related to the problem, and it doesn't seem to have an answer that solves it. So here's my solution.
Essentially, the issue is that knockout really wants your viewModel values to be a string, not a boolean, but this isn't always practical. So, I created a binding called "isChecked" which works strictly with booleans. Note: This will only work with observable properties.
ko.bindingHandlers.isChecked = {
getElementDeclaredValue: function (element) {
var declaredValue = element.getAttribute("value");
// If a value is provided, we presume it represents "true",
// unless its explicitly "false". If no value is provided, we
// presume that a checked state would equal "true".
return declaredValue && Boolean.isBool(declaredValue)
? Boolean.parse(declaredValue)
: true;
},
init: function (element, valueAccessor) {
var updateHandler = function () {
var declaredValue = ko.bindingHandlers.isChecked.getElementDeclaredValue(element);
var elementValue = element.checked ? declaredValue : !declaredValue;
var modelValue = valueAccessor();
var currentValue = ko.utils.unwrapObservable(modelValue);
if (elementValue === currentValue)
return;
if (ko.isObservable(modelValue)) {
modelValue(elementValue);
}
};
ko.utils.registerEventHandler(element, "click", updateHandler);
},
update: function (element, valueAccessor) {
var elementValue = ko.bindingHandlers.isChecked.getElementDeclaredValue(element);
element.checked = elementValue === ko.utils.unwrapObservable(valueAccessor());
}
};
The two Boolean methods ("parse" and "isBool") are defined as follows:
Boolean.isBool = function (value) {
return (/^(?:true|false)$/i).test(value);
};
Boolean.parse = function (value) {
return (/^true$/i).test(value);
};
I'll ignore any comments that say I shouldn't be modifying a built-in object prototype; I'll do as I damn well please ;-).
Usage is the same as the checked binding. The "value" attribute is optional, unless you want the checked state to represent false:
<input type="radio" id="rbNewClaim" name="ClaimType" value="false" data-bind="checked: isExistingClaim" />
Hope this helps someone.
I gave up trying to get this to work with the bool values and created an array of selected objects and handled it that way. It isn't the optimal solution, but I was tired of fighting this.

Resources