ExtJS 4 MVC, Get Checkbox value integer instead of bool - json

I'm using a form to edit Model. I receive data in JSON. Here's my problem:
I receive data for Checkbox only in INT: 1 or 0, I cannot change it. JSON:
{ "checkboxValue": 1 }
This field in ExtJS model is defined as INT type. Model:
{name: "checkboxValue", type: Ext.data.Types.INT},
then I set values to form this way:
formCmp.loadRecord(loadedStore.getAt(0));
and my checkbox is set correctly: when I receive 1 it's checked, 0 - unchecked.
But when I try to save record and send data to server this way:
form.updateRecord(form.getRecord());
record.save();
I need Checkbox to have also INT value - 1 or 0. But it has only BOOL value - true or false so when JSON is sent that value is NaN.
{
"checkboxValue": NaN
}
I think, that function .updateRecord(..) go through all elements and when it gets to checkbox it tries to get value, and the value is BOOL
Does anybody know how to make checkbox' output value INT?

Ext.form.Basic.updateForm uses getFieldValues method to retrieve new data for the updated record, while getFieldValues method returns only boolean values for checkboxes regardless of such properties as inputValue or uncheckedValue. So I would use convert function for the model's field to transform provided boolean value into an integer in a way like that:
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'flag',
type: 'int',
convert: function (v, record) {
return typeof v === 'boolean' ? (v === true ? 1 : 0) : v;
}
}
],
...
});
Here is a complete jsfiddle

I think it can be done with some simple overrides
Ext.create('Ext.form.Panel', {
bodyPadding: 10,
width: 300,
title: 'Pizza Order',
items: [
{
xtype: 'fieldcontainer',
fieldLabel: 'Toppings',
defaultType: 'checkboxfield',
items: [
{
boxLabel : 'Topping?',
name : 'topping',
id : 'checkbox1',
// include these two properties in your checkbox config
uncheckedValue: 0,
setValue: function(checked) {
var me = this;
arguments[0] = checked ? 1 : me.uncheckedValue;
me.callParent(arguments);
return me;
}
}
]
}
],
renderTo: Ext.getBody()
});

Related

Polymer update object outside of component and reflect changes to UI

Is it possible to reflect changes to polymer component property without update the value via .set(path, value).
For example I have object with overrided setter which based on this value apply new value to other field.
Polymer({
is: 'x-element',
properties: {
form: {type: Object,
value: {
set name(v) {
this._name = v;
this.additional = v; // change the different property
},
get name() {
return this.name;
},
set additional(v) {
// process v
this._additional = v; // field does not reflect
},
get additional() {
return this._additional;
}
},
reflectToAttribute: true
}
})

How to modify select objects in a JSON collection w/lodash

I'm looking for a performant way to update selected records in a collection based on the presence of the record's ID in a reference array. For example, given a reference array of [1,2,5] I want each record in the collection with those IDs to be given an attribute of $selected: true. Each record in the collection will be associated with a checkbox in the view and $selected items will be checked (fiddle)
I've started with the approach below (coffeescript) but I'm new to Lodash so I thought I'd ask for some feedback. Also, I'm not sure what the cleanest way is to set $selected: false to the alternate records?
# Whole Collection
collection = [
{id:1, name: "one"},
{id:2, name: "two"},
{id:3, name: "three"},
{id:4, name: "four"},
{id:5, name: "five"}
]
# Mark subset as selected
for id in [1,2,5]
_.where( collection, 'id':id ).forEach( (record) ->
record.$selected = true
)
Here's a fiddle...
http://jsfiddle.net/zd78e4bj/
EDIT
Added reference to two-way binding $selected elements to checkboxes in the view
I would do something like this (sorry it's not CoffeScript, but you get the idea):
var collection = [
{ id:1, name: 'one' },
{ id:2, name: 'two' },
{ id:3, name: 'three' },
{ id:4, name: 'four' },
{ id:5, name: 'five'}
];
var ids = [ 1, 2, 5 ];
_(collection)
.indexBy('id')
.at(ids)
.each(_.ary(_.partialRight(_.assign, { $selected: true }), 1))
.value();
console.log(collection);
// →
// [
// { id: 1, name: 'one', $selected: true },
// { id: 2, name: 'two', $selected: true },
// { id: 3, name: 'three' },
// { id: 4, name: 'four' },
// { id: 5, name: 'five', $selected: true }
// ]
First, we create an intermediary object using indexBy(). The keys are the id values in collection. Next, we pass at() the ids we're interested in. This builds a new collection containing only the ids we're after.
The last step is to use each() to add the $selected property. This is done by combining partialRight(), assign(), and ary(). The partially-applied argument is the new $selected property. We use ary() to make sure the callback passed to each() only has one argument.
You can use the map or forEach function to do all of this either in Lodash or native JavaScript. Map creates a new list and forEach will mutate the existing list.
The key to these is the transformation function. This function will set the $selected to true or false if it exists or not in the ids collection.
function mark(item) {
item['$selected'] = (ids.indexOf(item.id) > -1);
return item;
}
You could build a more generic transformer using:
function markItemByList(list, property, searchField) {
return function(item) {
item[property] = (list.indexOf(item[searchField]) > -1);
return item;
}
}
Coffeescript would be:
markItemByList = (list, property, searchField) ->
(item) ->
item[property] = (list.indexOf(item[searchField])) > -1)
item
If you want a mutable implementation:
function select(ids, collection) {
collection.forEach(markItemByList(ids, '$selected', 'id'));
}
Here's a lodash immutable implementation:
function select(ids, collection) {
return _.map(collection, markItemByList(ids, '$selected', 'id'));
}
Here's a pure JavaScript immutable implementation:
function select(ids, collection) {
return collection.map(markItemByList(ids, '$selected', 'id'));
}
Here's an angular implementation:
angular.forEach(collection, markItemsByList(ids, '$selected', 'id'));

yeoman generator : repeat a prompt

i'm create a custom yeoman generator, i need create an array base on user responses :
How can i repeat a question and push answer to an array ?
ex :
Add a value ? Y/n
if yes
Value = ?
Add a value ? Y/n
...
for the moment, i have this code :
MyGenerator.prototype.askFor = function askFor() {
var cb = this.async();
console.log(this.yeoman);
var prompts = [
{
type: 'confirm',
name: 'addvalue',
message: 'Add value ?',
default: true
},
{
name: 'myarray',
message: 'Value =',
}
];
this.prompt(prompts, function (props) {
this.addvalue = props.addvalue;
cb();
}.bind(this));
};
Just use a recursive function.
example (won't work as is because of this context):
function askSomething() {
this.prompt({ /* some prompts */ }, function (answers) {
// call the function back if needed
askSomething();
});
}

kendoAutoComplete expects that JSON reponse contains the same propertyname as the search filter

Datasource is defined as:
var KendoDataSource_EmployeeAutoCompleteByFirstName = {
serverFiltering: true,
serverPaging: true,
serverSorting: true,
pageSize: 10,
transport: {
read: {
url: '#Url.Action("GetEmployeesByFirstName", "Employee")',
dataType: "json"
}
}
};
AutoComplete is defined as:
function KendoGridFilterAutoComplete(element, kendoDataSource, textField) {
element.kendoAutoComplete({
minLength: 3,
filter: "startswith",
dataSource: kendoDataSource,
dataTextField: textField
});
}
When using a kendoAutoComplete widget, the filter which is send by the datasource is like:
filter[logic]=and&
filter[filters][0][value]=smith&
filter[filters][0][operator]=startswith&
filter[filters][0][field]=LastName&
filter[filters][0][ignoreCase]=true
The JSON response from the server looks like:
[
{"First":"Bill","LastName":"Smith"},
{"First":"Jack","LastName":"Smith"},
{"First":"ABC","LastName":"Smithy"}
]
This works fine, however as you can see I return multiple entries, so the kendoAutoComplete shows two the same entries (Smith) because the first-name differs.
So what I actually want is do distinct on the server, and return only the possible LastName, as an array of strings like this:
[
"Smith",
"Smithy"
]
However the kendoAutoComplete cannot handle this. It shows "undefined" or an error.
How to solve this ?
I've create the following code:
#region AutoComplete
public virtual IQueryable GetAutoComplete(KendoGridRequest request)
{
// Get filter from KendoGridRequest (in case of kendoAutoComplete there is only 1 filter)
var filter = request.FilterObjectWrapper.FilterObjects.First();
// Change the field-name in the filter from ViewModel to Entity
string fieldOriginal = filter.Field1;
filter.Field1 = MapFieldfromViewModeltoEntity(filter.Field1);
// Query the database with the filter
var query = Service.AsQueryable().Where(filter.GetExpression1<TEntity>());
// Apply paging if needed
if (request.PageSize != null)
{
query = query.Take(request.PageSize.Value);
}
// Do a linq dynamic query GroupBy to get only unique results
var groupingQuery = query.GroupBy(string.Format("it.{0}", filter.Field1), string.Format("new (it.{0} as Key)", filter.Field1));
// Make sure to return new objects which are defined as { "FieldName" : "Value" }, { "FieldName" : "Value" } else the kendoAutoComplete will not display search results.
return groupingQuery.Select(string.Format("new (Key as {0})", fieldOriginal));
}
public virtual JsonResult GetAutoCompleteAsJson(KendoGridRequest request)
{
var results = GetAutoComplete(request);
return Json(results, JsonRequestBehavior.AllowGet);
}
#endregion
Which returns a unique list of anonymous objects which look like { "LastName" : "a" }.

Property label not found on String and there is no default value

Based on the following data
public var dataArray:ArrayCollection = new ArrayCollection( [
{ label: "None", data: '' },
{ label: "Some Data", data:
{
label: "String tested at IF", data: "20"
}
}
]);
I then create a new ArrayCollection obj based on the position a user has selected from a dropdown list
var skillArrayCollection:ArrayCollection = ArrayCollection(runtimeComponents[dataArray[classSelect.selectedIndex].data]);
I am looping through an ArrayCollection object like so:
for each (var item:Object in skillArrayCollection[charSkillOne.selectedIndex]) {
if (item.label == "somelabel") {
ret = ret + Number(item.data);
}
}
When the if statement does its check 'it matches the string test and returns the correct result; IT also returns the error: ReferenceError: Error #1069: Property label not found on String and there is no default value.
I do not understand how flex will error and return the result i have asked for?
In your first object here:
{ label: "None", data: '' },
{ label: "Some Data", data:
{
label: "String tested at IF", data: "20"
}
}
data is a string, in your second object, data is an object with a label property.
When your loop goes through each element there the first would cause this error because when you call object.data.label on it you're trying to get a label property of a string, hence the error (for the second object if it were to get there it would not error). As others state the question leaves out the contents of runtimeComponents so it's difficult to say this is for sure the issue but it seems right.