Formating date values for display in Can.js - canjs

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.

Related

Why kendo Ui -grid date is not sorting properly?

value is ReinsDepositAmount
**
output
**
I have recently stocked with one of the application date sorting in the kendo UI grid.
In kendo grid, the column name is defined like this
Incoming value to ReinsDepositDate - Month,date,year format. 08-23-1991
Field name is ReinsDepositDate:
{
field: "ReinsDepositDate", type: "date", title: "Due Date",format: "{0:M/d/yyyy}", width: 100, filterable: {
cell: {
operator: "contains"
}
}
},
When Sorting the date, its sorting based on first values
1/12/1994
23/1/2015
13/1/1992
means while ascending I am getting
1/12/1994
13/1/1992
23/1/2015
So I have put the schema model
still, I am getting the same result.
schema: {
model: {
fields: {
ReinsDepositDate: { type: "date",format: "{0:dd/MM/yyyy}"}
}
}
},
I have seen lots of fiddle demos nothing works here why:
Refrences:
http://fiddle.jshell.net/NqrDS/light/
Kendo grid date column not formatting
Flow of Design:
Flow of design is by using angular Http service get the value from DB through API and assign the response to datasource in the kendo grid. when I doing a demo with JSON files, its working fine. But the same thing applies it here means not working. so I went to custom javascript to sort. columns:[$scope.grdPrmiumDepositCol, –
Custom javascript in kendo sortable attribute will do the trick.
working fine do this part.
{ field: "ReinsDepositDate", format: "{0:MM/dd/yyyy}",type:"date", sortable:{ compare: function (a, b) {
var c = new Date(a.ReinsDepositDate);
var d = new Date(b.ReinsDepositDate);
return c - d;
}`
}}],
My Question is why I do that because kendo is given the date format and when I tried the sample demo with transport read with JSON file working fine with kendo format. Still in confusion.
Based on the provided information, it is unclear if sorting is performed on the client, or on the server.
If sorting is done on the client by the Kendo UI DataSource, then the date values should be provided in the correct format, so that they are parsed to JavaScript Date objects by Kendo UI. There are multiple different formats that can be parsed, but dd-MM-yyyy is not one of them.
Here is an example, which demonstrates the above. You will notice the empty row, where the date has not been parsed.
http://dojo.telerik.com/UcEXO/2
Generally, it is recommended to serialize dates using commonly accepted standards:
https://stackoverflow.com/a/15952652/3086237
If sorting is performed on the server, then Kendo UI is unrelated to the problem and you should debug the server-side implementation.
You can try parsing the date from response.
http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-schema.parse
schema: {
parse: function(response) {
for (var i = 0; i < response.length; i++) {
response[i].ReinsDepositDate = kendo.parseDate(response[i].ReinsDepositDate, "dd/MM/yyyy");
}
return response;
}
}
Hope this helps.

DateRangePicker doesn't recognise carbon date

Using Vue.js ( Vue-Tables https://www.npmjs.com/package/vue-tables ) with laravel.
The data is being succesfully displayed, but the daterangepicker (http://www.daterangepicker.com/) is not sorting at all.
No matter what interval I set, the records won't display. The field is being parsed with carbon to return in needed format
public function getFootageDateAttribute($date)
{
return Carbon::parse($date)->format('d-m-Y');
}
In the js file, I have dateFormat: "DD-MM-YY", filterByColumn: true, dateColumns: ['footage_date'], . When I inspect with vue dev-tools, the field is footage_date: "03-04-2016"
If I hardcode the date as in the example ( https://jsfiddle.net/matfish2/f5h8xwgn/ ) using
// Courtesy of Tomasz Nurkiewicz (Elegant method to generate array of random dates within two dates)
function randomDate(start, end) {
return moment(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
}
the date is in this format footage_date: "1974-03-27T18:19:40.364Z" and it works.
Pastebin of the full js file http://pastebin.com/6hCe2eQL . Client side http://pastebin.com/xTUcAK98
The footage_date was supposed to be passed as a moment instance, not as a date string, therefore, modifying the ready function did it
ready: function(){
this.$http.get('/api/footage')
.then(function(response){
footages = response.data
footages.forEach(footage => {
footage.footage_date = moment(footage.footage_date)
})
this.tableData = footages
}.bind(this))
}

using a function defined in a kendo model later in that model

OK, I'm obviously not understanding how functions are used in javascript. Given the below code snippet, mozilla firefox is telling me that calcUpper is not defined. Basically I want to define a function and use that function later on in the view on different fields. I tried moving the function definition outside of the kendo model, but with no better results. Can someone show me how I can achieve this?
var viewModel = kendo.observable({
calcUpper: function (fieldName) {
var value = this.get(fieldName);
if (value == "")
return "";
else
return parseInt(value) - 1;
},
jobNum: '',
SRCPerif: '',
SRCOnTargetUpper: calcUpper('SRCPerif'),
SRCOnTargetLower: '',
SRCConcernUpper: calcUpper('SRCOnTargetLower'),
//...other fields...
});

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!

BreezeJS does not automatically parse numbers saved as strings with KnockoutJS bindings

I queried my database using Breezejs using the following code:
viewModel = {
products = ko.observableArray([])
};
var manager = new entityModel.EntityManager('/api/Products');
manager.executeQuery(query)
.then(function (data) {
viewModel.products.removeAll();
viewModel.products(data.results);
});
However the products rows contain numeric properties like Quantity which are wired to my page using the data-bind property. On saving the model through manager.saveChanges() I get a validation error. This is because KnockoutJS saves the edited numbers as strings.
What's the recommended way to get around this issue?
As of breeze v 0.80.2, this capability is now supported. ( along with the capability to customize type coercion)
One option is to create a CustomBinding.
I use this for decimals:
ko.bindingHandlers.decimal = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
$(element).blur(function () {
var value = valueAccessor();
var valor = Globalize.parseFloat($(element).val());
if (ko.isWriteableObservable(value)) {
value(valor);
ko.bindingHandlers.decimal.update(element, valueAccessor);
}
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).val(Globalize.format(value, "n2"));
}
};
It's a good question.
Currently, breeze does not attempt type coercion, but...
We have discussed having Breeze automatically attempt to coerce any values used within a set operation to the datatype of the property being set ( as defined in breeze metadata). This would occur across all binding libraries, (i.e angular, backbone etc) as well as knockout.
Please feel free to add this to the breeze User Voice. We take these submissions very seriously.

Resources