Very odd event behaviour for onChange on Telerik MVC DatePicker - asp.net-mvc

To the question started, my code (I'll try to only include relevant portions to start), starting with my script:
function RaceDate_onChange() {
var pickedDate = $(this).data('tDatePicker').value();
var month = pickedDate.getMonth() + 1;
$.get("/RaceCard/Details?year=" + pickedDate.getFullYear() + "&month=" + month + "&day=" + pickedDate.getDate());
}
Then my markup:
#Html.Telerik().DatePickerFor(model => model.RaceDate).ClientEvents(events => events.OnChange("RaceDate_onChange"))
And finally a bit of the receiving action:
[HttpGet]
public ActionResult Details(int year, int month, int day)
{
var viewModel = new RaceCardModel {Metadata = DetailModelMetadata.Display, RaceDate = new DateTime(year, month, day)};
I'm trying to get the selection of a new date to trigger a GET, to refresh the page without submitting a form. This works fine, except for this problem:
In GET requests to the Details action, the day value is always one day behind the DatePicker. E.g. The first value is set from a view model property, when the view is rendered, say 3. I then click on 14 and hit my breakpoint in the action method. The day value is 3. When I click on 29 and hit the breakpoint, the day value is 14.
Besides asking what is wrong, I'll take a liberty and ask if there is a better way that is no more complicated. I am fairly novice and would rather deliver working code that needs revision than get bogged down in tangents and details.

Try using e.value instead as shown in the client-side events example. You are probably using an older version where the value() method returned the previous value during the OnChange event.
UPDATE:
"e.value" means the value field of the OnChange arguments:
function onChange(e) {
var date = e.value; // instead of datePicker.value()
}

As far as the 1 month difference you are getting, that's normal, and it is how the getMonth() method works in javascript on a Date instance:
The value returned by getMonth is an
integer between 0 and 11. 0
corresponds to January, 1 to February,
and so on.
So adding +1 is the correct way to cope with the situation, exactly as you did.
Just a little remark about your AJAX call: never hardcode urls. Always use url helpers when dealing with urls:
var year = pickedDate.getFullYear();
var month = pickedDate.getMonth() + 1;
var day = pickedDate.getDate();
var url = '#Url.Action("Details", "RaceCard")';
$.get(url, { year: year, month: month, day: day }, function(result) {
// process the results of the AJAX call
});

Related

Displaying a human readable date time in angular js that comes from rails backend

I want to show human readable date time in my frontend. My data comes from rails backend. When I use {{ item.created_at }} it shows the time like rails way 2016-10-10T10:29:47.993Z. But How can I show this like 5 days ago, 3 hours ago in angular js?
To format dates in angular you can use date filter like this:
{{ item.created_at | date:'yyyy-MM-dd HH:mm' }}
You are looking for a very particular format so I think you need to build a custom filter to show exactly that. You can use this filter scaffolding:
.filter('customDate', function() {
return function(date) {
// 1. Get current date
// 2. Get diff from expression date to current
// 3. Apply your format and return result;
};
});
Lastly there is a library called momentjs to manipulate dates and times and there is an angular version of that:
Check the am-time-ago directive of the library:
<span am-time-ago="item.created_at"></span>
Try this, Create a filter for that, for reusability of code
var jimApp = angular.module("mainApp", []);
jimApp.controller('mainCtrl', function($scope){
$scope.date = "1992-05-07T22:00:00.000Z";
});
jimApp.filter('dateFilter', function() {
function calculateDate(date) {
date = new Date(date);
var year = date.getFullYear();
var month = date.getMonth()+1;
var day = date.getDate();
return day+'-'+month+'-'+year;
}
return function(date) {
return calculateDate(date);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="mainApp" ng-controller="mainCtrl">
<div>{{date | dateFilter}}</div>
</div>

date_select save higher day of the month available

I have a simple datetime attribute to pick a date like this on the views
= f.date_select :period_end_at, default: { day: 31 }
It defaults to last day of the month as the example. The problem is that if month selected is "June" that has 30 days, since there is no '31' day for June, it will save the object as day 1 instead of day 30.
Is there an easy way to always save to the highest day of the month if the value provided is above all available for that moonth?
Not sure if it could be shortened, but this should work (if I understood your question correctly):
= f.date_select :period_end_at, default: { day: Time.days_in_month(Time.now.month) }
Take a look at this js snippet, it works well for me with Rails 4.2.0
<script>
$(function(){
railsMonthDates();
$("select[id*=_2i], select[id*=_1i]").change( railsMonthDates );
});
function railsMonthDates() {
$("select[id*=_2i]").each(function(){
$monthSelect = $(this);
$daySelect = $(this).siblings("select[id*=_3i]");
$yearSelect = $(this).siblings("select[id*=_1i]");
var year = parseInt($yearSelect.val());
var month = parseInt($monthSelect.val());
var days = new Date(year, month, 0).getDate();
var selectedDay = $daySelect.val()
$daySelect.html('');
for(var i=1; i<=days; i++) {
$daySelect.append('<option value="'+i+'">'+i+'</option>');
}
$daySelect.val(selectedDay);
});
}
</script>
Simply paste it into the partial which has the form.
Pay attention, it match every element which has id*=_1i, id*=_2i or id*=_3i, so if you have more f.date_select you need to specify a better matcher.

How to display previous value on Min Miles text field

I want to display a previous value on Min Miles and that should not be editable. I want like
Default value of Min Miles is 0.
When I click on Add More Range then In the new form - Min Value should be Max Value of Previous Form.
I am using semantic form for. Please Help Me. How can I do this...
Regarding your second question, and assuming that the new form appears through javascript, without page reloading, you can grab the
field value with javascript and use it as the default value for the
new field. The "add new range"
Something Like
function getvalue(){
var inputTypes_max = [],inputTypes_min = [],inputTypes_amount = [];
$('input[id$="max_miles"]').each(function(){
inputTypes_max.push($(this).prop('value'));
});
$('input[id$="amount"]').each(function(){
inputTypes_amount.push($(this).prop('value'));
});
var max_value_of_last_partition = inputTypes_max[inputTypes_max.length - 2]
var amount_of_last_partition = inputTypes_amount[inputTypes_amount.length - 2]
if (max_value_of_last_partition == "" || amount_of_last_partition == "" ){
alert("Please Fill Above Details First");
}else{
$("#add_more_range_link").click();
$('input[id$="min_miles"]').each(function(){
inputTypes_min.push($(this).prop('id'));
});
var min_id_of_last_partition=inputTypes_min[inputTypes_min.length - 2]
$("#"+min_id_of_last_partition).attr("disabled", true);
$("#"+min_id_of_last_partition).val(parseInt(max_value_of_last_partition) + 1)
}
}
I have Used Jquery's End Selector In a loop to get all value of max and amount field as per your form and get the ids of your min_miles field and then setting that value of your min_miles as per max_miles
It worked For me hope It works For You.
Default value of a field can just be passed in the form builder as a second parameter:
...
f.input :min_miles, "My default value"
Of course I do not know your model structure but you get the idea.
Regarding your second question, and assuming that the new form appears through javascript, without page reloading, you can grab the field value with javascript and use it as the default value for the new field. The "add new range" click will be the triggerer for the value capture.
Something like (with jQuery):
var temp_value = '';
$('#add_more_range').click(function(){
temp_value = $('#my_form1 #min_miles').value();
$('#my_form2 #max_miles').value(temp_value);
});
Again I am just guessing the name of the selectors, but the overall approach should work.
If you are also adding dinamically to the page the "Add new range" buttons/links, then you should delegate the function in order to be inherited also for the so new added buttons:
$('body').on('click', '#add_more_range', function(){...});

Working with dates in breeze

I'm having some trouble working with dates.
I have an object with a date field:
public DateTime FechaInicio{get; set;}
This definition generates the following field in the database:
FechaInicio datetime not null
Making the request to the web service I get the date ( in the JSON ) in the following format:
"FechaInicio": "1982-12-02T00: 00:00"
And calling FechaInicio() on tne entity returns a javascript Date object.
Creating a new entity I get the following value:
createPalanca var = function () {
MetadataStore var = manager.metadataStore;
metadataStore.getEntityType palancaType = var ("Toggle");
palancaType.createEntity newPalanca = var ();
manager.addEntity (newPalanca);
//Here: newPalanca.FechaInicio () has the value in this format: 1355313343214
//Expected Date object here
newPalanca return;
};
After all, my real question is: What format should I use to assign new values ​​to date type fields?
Edit:
After doing some tests, I noticed that if I assign a Date object to the property, everything seems fine until we got to this line:
saveBundleStringified var = JSON.stringify (saveBundle);
saveBundle content is:
FechaInicio: Thu Dec 20 2012 00:00:00 GMT+0100 (Hora estándar romance)
and the saveBundleStringified:
"FechaInicio": "2012-12-19T23:00:00.000Z" <- I guess this is utc format
What finally is stored in the database is: 2012-12-19 23:00:00.0000000
When the result of the call to SaveChanges are returned , they are merged with the entities in cache at the function updateEntity which does this check: if (!core.isDate(val)) that returns false.
As a consequence it is created a new Date object with the wrong date:
function fastDateParse(y, m, d, h, i, s, ms){ //2012 12 19 23 00 00 ""
return new Date(y, m - 1, d, h || 0, i || 0, s || 0, ms || 0);
}
Correct me if I'm wrong, but I think that's the problem.
Sorry for taking so long...
There were bugs with Breeze's DateTime timezone serialization and the default DateTime values used for newly constructed entities with non-nullable date fields. These are fixed as of v 0.77.2. Please confirm if this set of fixes works for you.
And thanks for finding these.
And to answer your question, all date properties on your object should be set to javascript Dates. Breeze should handle all of the serialization issues properly.
Dates always scare me. My immediate instinct is that the browser and server are not on the same TimeZone; how that could be I don't know. In any case, it's bound to happen and I recall all kinds of fundamental problems with coordinating client and server on datetime. I think the usual recommendation has always been to keep everything in UTC and adjust what you display to the user in local time.
I rather doubt this is a helpful answer. I'm not sure what part Breeze should play in resolving this. Would welcome a suggestion that we can circulate and build consensus around.
Also can you clarify this statement:
When the result of the call to SaveChanges are returned , they are merged with the entities in cache at the function updateEntity which does this check: if (!core.isDate(val)) that returns false. As a consequence it is created a new Date object with the wrong date
What do you mean by "the wrong date"? And are you saying that Breeze thinks the incoming date value is in an invalid format (as opposed to being a date other than the one you expected)?
Yes, #Sascha, Breeze is using the Web Api standard for JSON formatting (Json.Net) and it is set for ISO8601 format as opposed to the wacky Microsoft format (which escapes me as I write this).
Breeze/Web Api seem to need the dates in some special format (ISO8601). Any other format did not work for me. moment.js solved the problem for me with setting and reading. Formatting is also nicely done if you use Knockout to display the date with a special binding.
entity.someDate(moment().utc().toDate()) // example
and it works.
You could also use this:
Date.prototype.setISO8601 = function(string) {
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
var d = string.match(new RegExp(regexp));
var offset = 0;
var date = new Date(d[1], 0, 1);
if (d[3]) {
date.setMonth(d[3] - 1);
}
if (d[5]) {
date.setDate(d[5]);
}
if (d[7]) {
date.setHours(d[7]);
}
if (d[8]) {
date.setMinutes(d[8]);
}
if (d[10]) {
date.setSeconds(d[10]);
}
if (d[12]) {
date.setMilliseconds(Number("0." + d[12]) * 1000);
}
if (d[14]) {
offset = (Number(d[16]) * 60) + Number(d[17]);
offset *= ((d[15] == '-') ? 1 : -1);
}
offset -= date.getTimezoneOffset();
time = (Number(date) + (offset * 60 * 1000));
this.setTime(Number(time));
};

How do I find that March 2nd and March 3rd falls between March 1st and March 4th?

I need a way to find these in grails:
1) I have two dates say start and end.
2) User selects two dates in the browser say them userStartDate and userEndDate.
I have all these values, but I need to write a query that do find that both start and end falls between userStartDate and userEndDate.
For example, March 2nd and March 3rd falls between March 1st and March 4th. Given that :
March 2nd and March 3rd are userStartDate and userEndDate dates respectively
March 1st and March 4th are start and end respectively. (they are domain objects).
I have this code which works for between cases i.e start is in between userStartDate and userEndDate like so :
test = Holiday.createCriteria().list {
and {
user {
eq('username',username)
}
or {
between('start',userStartDate,userEndDate)
between('end',userStartDate,userEndDate)
}
}
}
As according to my question, how can attach that part into my code?
Thanks in advance.
Assuming that you already do a check that userStartDate is before userEndDate (validated when the user selects) and that start is before end in the database (validated when inserting), the criteria query should look something like this:
test = Holiday.createCriteria().list {
user { eq('username',username) }
lt('start', userStartDate)
gt('end', userEndDate)
}
This checks that start is less than (i.e. before) userStartDate and that end is greater than (i.e. after) userEndDate. There is also no need to wrap in an and block since all clauses are implicitly and-ed.
Date provides before and after methods (http://docs.oracle.com/javase/6/docs/api/)
if(start.after(userStartDate) && start.before(userEndDate))
{
//start is between userStartDate && userEndDate
}
The simplest way to figure out if one date is between two others is using a Range object
def start = new Date()
def end = new Date() + 10
// make a date range
def dateRange = start..end
// test if some dates are within the range
def inRange = new Date() + 5
def outsideRange = new Date() + 50
assert inRange in dateRange
assert !(outsideRange in dateRange)
However, you mentioned that you want to compare dates in a query, so a Groovy solution may not be optimal. Here's an example for checking if someone's birthday is between 2 dates using a criteria query
def start = new Date()
def end = new Date() + 10
def results = User.withCriteria {
between('birthday', start, end)
}

Resources