How to restrict a input field numeric in knockout js [duplicate] - validation

This question already has answers here:
make an input only-numeric type on knockout
(10 answers)
Closed 8 years ago.
I have an input field and i want to restrict it only for numeric values. How can i do it in knockout js
here is my field
<input data-bind="value: nsc" />

You can write a function in your view model.
ko.extenders.numeric = function(target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({ notify: 'always' });
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
Check this link how to use : Sample code

Guess this question is already answered.
You may need to create custom binding which accepts only allowed characters.
The answer to the post in this link will help you: make an input only-numeric type on knockout

Related

ExtJS 6: TreePicker does not fire change event

See fiddle here: https://fiddle.sencha.com/#fiddle/2iig&view/editor
The docs (https://docs.sencha.com/extjs/6.6.0/classic/Ext.ux.TreePicker.html#event-change) list 'change' in the events section but when I set the value or reset the field this event never fires. The 'select' event fires as expected but that only fires when the user selects a field.
EDIT:
Based on Snehal's suggestion below, I was able to accomplish this using the following override. Not sure if there is a simpler way to do it but this was the best I could manage:
Ext.define('MyApp.overrides.TreePicker', {
override: 'Ext.ux.TreePicker',
setValue: function (value) {
var me = this,
record;
me.value = value;
if (me.store.loading) {
// Called while the Store is loading. Ensure it is processed by the onLoad method.
return me;
}
// try to find a record in the store that matches the value
record = value ? me.store.getNodeById(value) : me.store.getRoot();
if (value === undefined) {
record = me.store.getRoot();
me.value = record.getId();
} else {
record = me.store.getNodeById(value);
}
// zeke - this is the only line I added to the original source
// without this the 'change' event is not fired
me.callSuper([value]);
// set the raw value to the record's display field if a record was found
me.setRawValue(record ? record.get(me.displayField) : '');
return me;
}
});
Because setValue function does not call this.callParent(). You can do something like this in setValue function.
setValue: function(value) {
var me = this,
record;
if (me.store.loading) {
// Called while the Store is loading. Ensure it is processed by the onLoad method.
return me;
}
// try to find a record in the store that matches the value
record = value ? me.store.getById(value) : me.store.getRoot();
me.callParent([record.get('valueField')]);
return me;
},

check if d3.select or d3.selectAll

I have a method on a reusable chart that can be passed a selection and return a value if it is passed a d3.select('#id') selection or an array of values if it is passed a d3.selectAll('.class') selection. I'm currently interrogating the passed argument with context._groups[0] instanceof NodeList, but it feels a little fragile using an undocumented property, as that may change in future versions. Is there a more built in way of determining if a selection comes from select or selectAll?
selection.size() will not help here, as it only tells us the result of the selection, not how it was called.
EDIT:
Here's the context of the use. I'm using Mike Bostock's reusable chart pattern and this instance includes a method for getting/setting a label for a donut.
To me, this API usage follows the principle of least astonishment, as it's how I would expect the result to be returned.
var donut = APP.rotatingDonut();
// set label for one element
d3.select('#donut1.donut')
.call(donut.label, 'Donut 1')
d3.select('#donut2.donut')
.call(donut.label, 'Donut 2')
// set label for multiple elements
d3.selectAll('.donut.group-1')
.call(donut.label, 'Group 1 Donuts')
// get label for one donut
var donutOneLabel = d3.select('#donut1').call(donut.label)
// donutOnelabel === 'Donut 1'
// get label for multiple donuts
var donutLables = d3.selectAll('.donut').call(donut.label)
// donutLabels === ['Donut 1', 'Donut 2', 'Group 1 Donuts', 'Group 1 Donuts']
and the internal method definition:
App.rotatingDonut = function() {
var label = d3.local();
function donut() {}
donut.label = function(context, value) {
var returnArray;
var isList = context._groups[0] instanceof NodeList;
if (typeof value === 'undefined' ) {
// getter
returnArray = context.nodes()
.map(function (node) {return label.get(node);});
return isList ? returnArray : returnArray[0];
}
// settter
context.each(function() {label.set(this, value);});
// allows method chaining
return donut;
};
return donut
}
Well, sometimes a question here at S.O. simply doesn't have an answer (it has happened before).
That seems to be the case of this question of yours: "Is there a more built in way of determining if a selection comes from select or selectAll?". Probably no.
To prove that, let's see the source code for d3.select and d3.selectAll (important: those are not selection.select and selection.selectAll, which are very different from each other).
First, d3.select:
export default function(selector) {
return typeof selector === "string"
? new Selection([[document.querySelector(selector)]], [document.documentElement])
: new Selection([[selector]], root);
}
Now, d3.selectAll:
export default function(selector) {
return typeof selector === "string"
? new Selection([document.querySelectorAll(selector)], [document.documentElement])
: new Selection([selector == null ? [] : selector], root);
}
As you can see, we have only two differences here:
d3.selectAll accepts null. That will not help you.
d3.selectAll uses querySelectorAll, while d3.select uses querySelector.
That second difference is the only one that suits you, as you know by now, since querySelectorAll:
Returns a list of the elements within the document (using depth-first pre-order traversal of the document's nodes) that match the specified group of selectors. The object returned is a NodeList. (emphasis mine)
And querySelector only...:
Returns the first Element within the document that matches the specified selector, or group of selectors.
Therefore, the undocumented (and hacky, since you are using _groups, which is not a good idea) selection._groups[0] instanceof NodeList you are using right now seems to be the only way to tell a selection created by d3.select from a selection created by d3.selectAll.

Formating date values for display in Can.js

All my dates come formatted as ISO 8601 from the backend, eg 2014-01-01T12:45:30Z. Across the application, I want to display them in different formats...
shorthand in tables, eg Jan 1
longer, more explicit format on a detailed view, eg Monday, January 1st.
Solution I made a helper where I can pass in the format. Easy enough.
can.mustache.registerHelper('formatDate', function(date, format) {
return date() ? moment(date()).format(format) : '-';
});
Problem Now I'm implementing the bootstrap datepicker, how can I capture these requirements...
the date in my model is formatted as ISO
bind to input with can-value in template
display format MM/DD/YY for users and datepicker
Bonus points if I don't need to make a compute for every single date value in my models, as they're quite large and with many dates.
Unfortunately there isn't a nice API for this(yet). However, you can achieve custom formats in a view while keeping your model properties pristine with the below code.
can.view.attr('can-somecustom-value', function(el, data) {
var attr = el.getAttribute('can-somecustom-value'),
value = data.scope.computeData(attr, {
args: []
}).compute;
new FormattedValue(el, {
value: value
//value is the only one we really care about, but
//you could specify other arbitrary options here
//such as "format: 'MM/DD/YYYY' to be used in your __format methods below"
});
});
var FormattedValue = can.Control.extend({
init: function () {
this.set();
},
__format: function() {
// return formatted version of this.options.value;
},
__deformat: function() {
// return this.element[0].value sans format(keeps your model pristine);
},
'{value} change': 'set',
set: function () {
if (!this.element) {
return;
}
var self = this;
setTimeout(function() {
self.element[0].value = self.__format();
});
},
'change': function () {
if (!this.element) {
return;
}
this.options.value(this.__deformat());
}
});
This will allow you to do the following:
<input can-somecustome-value="myDateProp"/>
where "myDateProp" is an attribute on some can.Map/can.Model/etc.
This will result in the input displaying a custom string format, while someModel.attr('myDateProp') will still return the ISO format(which in turn means the ISO format will also be saved to the server).
There is some internal discussion regarding adding filters/parsers to allow control over formats specific only to view rendering.

How to override or change comparator on backbone collection? [duplicate]

This question already has answers here:
correctly implement backbone comparators
(2 answers)
Closed 8 years ago.
I have a backbone collection called Topics that in one instance in my app I would like sorted by a property I have called view_count.
Another instance of the Topics collection I want to be sorted by name alphabetically.
Currently, on the collection, I have a comparator:
comparator: (topic) ->
return topic.get('view_count') * -1
When I want the collection to be sorted by name rather than view_count, what is an elegant way to override or change the comparator/sorting options? I have tried to declare the comparator function on each initialization of the Topics collection bu that doesn't seem to work correctly.
Change your collection to:
var Topics = Backbone.Collection.extend({
initialize: function(options) {
this.sortProperty = options.sortProperty;
},
comparator: function(topic) {
if(this.sortProperty == "view_count")
return topic.get("view_count") * -1;
else
return topic.get("name");
}
});
then when you instantiate your collection:
var topics1 = new Topics({sortProperty : "view_count"});
var topics2 = new Topics({sortProperty : "name"});
You can also change the sorting property after initializing a collection using:
topics1.sortProperty = "name";

Knockout validation issues

I have the following issues with my knockout model validations and not sure how to resolve them. Following is my model first of all, with the validation rules:
var Data = function (data) {
this.Val = data;
}
function ViewModel(item) {
var parse = JSON.parse(item.d);
var self = this;
this.Name = ko.observable(parse.Name);
this.UserType = ko.observable(parse.UserType);
this.ID = ko.observable(parse.ID).extend({ required: { params: true, message: "ID is required" }, decimal: { params: 2, message: "Should be decimal"} });
this.Username = ko.observable(parsed.Username).extend({ required: {
onlyIf: function () {
return self.UserType() > 1;
}
}
});
this.WeeklyData = ko.observableArray([]);
var records = $.map(parse.WeeklyData, function (data) { return new Data(data) });
this.WeeklyData(records);
this.WeeklyData2 = ko.observableArray([]);
var records = $.map(parse.WeeklyData2, function (data) { return new Data(data) });
this.WeeklyData2(records);
}
ko.extenders.numeric = function (target, precision) {
var result = ko.dependentObservable({
read: function () {
return target().toFixed(precision);
},
write: target
});
result.raw = target;
return result;
};
Here are my problems:
1) with the ID() observable, I want to restrict it to two decimal points, so I've created the validation extender 'numeric' but it's not working. Is there anything wrong with how I'm using it and how to correct it?
2) Also, if I want to restrict an observable to whole numbers, how can I do that?
3) when I define a rule with a condition, (i.e. Username()), how do I define a custom message for that? I was able to do it for default rules, but with the conditional rules, it's not working
4) I have two observable arrays WeeklyData1 and WeeklyData2 both of which contains Data() objects. I want to have separate min/max rules for these two, for example, min/max - 1,7 for WeeklyData1 and min/max - 1,150 for WeeklyData2. How can I get it done?
4) Right now my error messages appear right next to the data field, but I want all those to appear in a single validation summary, while displaying '*' against the field. I've been told to use Validation-bindings, but I'm not sure how to use it, can someone please give an example?
It's a lot of questions, I know, but I appreciate if someone could help.
Thanks in advance
Instead of diving in your code i have created a small-small demonstrations for your questions. Ok so here we go,
1) with the ID() observable, I want to restrict it to two decimal points.... and 2) Also, if I want to restrict an observable to whole numbers....
Your 1 and 2 question are pretty similar so i covered both of this in a single fiddle. Check this fiddle.
3) when I define a rule with a condition, (i.e. Username()), how do I define a custom message ....
You can use message property to set custom messages, Check this fiddle.
4) I have two observable arrays WeeklyData1 and WeeklyData2 both of which contains Data() objects
I am not clear which this question, what type of data both of these array contains and for what you want to set min/max rule ( array length or other ). So please clear this, than i will try to help on this.
5) Right now my error messages appear right next to the data field.....
This questions answer i already given in your how to? with knockout js validations question (Check update).
Let me know if it helps!

Resources