I have a date range picker and I need to add a listener everytime i change the range of the values so i sent the startDate and endDate in my url to a restapi and then make a query to my databse with that valeus and get new rows.
My problem is with the listener.. I need something like "onChange" when i set new dates.
View:
<div class="form-group col-md-3 mb0" ng-if="timerange == 'custom'">
<div class="row">
<label class="col-sm-3 control-label pt7">Custom</label>
<div class="col-sm-9">
<input type="text" id="customrange" name="customrange" ng-model="parent.customrange" ng-change="applyOptions()" class="form-control" ui-jq="daterangepicker" ui-options="{format: 'YYYY/MM/DD',startDate: '{{startdate}}',endDate: '{{enddate}}', maxDate:'{{enddate}}'}" />
</div>
</div>
</div>
Controller:
var rangeSelector = document.getElementsByTagName('select')[1]; //1h 24h 1w custom
if(rangeSelector.value == 'custom'){
var datePicker = document.getElementById("customrange").getAttribute('ui-options');
var split = datePicker.split(",");
var startDate = split[1].split(': ')[1].replace(/["']/g, '');
var endDate = split[2].split(': ')[1].replace(/["']/g, '');
if (startDate !== undefined) {
url += '&startDate='+startDate;
}
if (endDate !== undefined) {
url += '&endDate='+endDate;
}
i tried 2 optiuons but i cant get into that code when i put a breakpoint on it..
$scope.$watch("customrange", function() {
console.log("I've changed : ");
});
and
rangeSelector.addEventListener("change", function(e){
if(rangeSelector.value == "custom"){
e.preventDefault();
customrange = document.getElementById("customrange");
customrange.addEventListener("change", function(){
startEndDate = controllerScope.getStartEndTimestamps();
});
}
}, false);
Anyone can help me please??
Image of problem
Updated:
The problem is that your $watch is not checking the correct model.
Your $watch should be called as follows:
$scope.$watch("parent.customrange", function(newValue, oldValue) {
console.log("I've changed : ");
});
To watch the object "parent":
$scope.$watch("parent", function(newValue, oldValue) {
console.log("I've changed : ");
}, true);
The true sets the optional objectEquality check.
Angular $watch Documentation:
When objectEquality == true, inequality of the watchExpression is determined according to the angular.equals function. To save the value of the object for later comparison, the angular.copy function is used. This therefore means that watching complex objects will have adverse memory and performance implications.
Related
<input
type="text"
datetime-picker
date-format="dd-MM-yyyy hh:mm a"
future-only
readonly
name="flg_{{user.user_id}}"
ng-model="orderItems[user.user_id].flg_time"
ng-click="saveOrder(user, orderItems[user.user_id])"
>
<input
type="text"
datetime-picker
date-format="dd-MM-yyyy hh:mm a"
future-only
name="dep_{{user.user_id}}"
ng-model="orderItems[user.user_id].dep_time"
ng-click="saveOrder(user, orderItems[user.user_id])"
>
var userInfo = auth.getCurrentUser().children;
angular.forEach(userInfo, function(item, key){
$scope.$watch('[orderItems[item.user_id].flg_time, orderItems[item.user_id].dep_time]', function(newVal, oldVal){
console.log("N", newVal); // undefined
console.log("O", oldVal); // undefined
if (newVal !== oldVal && typeof oldVal !== 'undefined') {
var orderItems = {
'order_id' : $scope.order.order_id,
'flg_time' : newVal[0],
'dep_time' : newVal[1],
}
$scope.saveOrder(item, orderItems);
}
}, true);
});
What i want to set value of new value into the original text box but it always says old and new value is undefined it should return the input value please guide what's wrong in it.
Thanks in advance
instead of $scope.$watch use $scope.$watchcollection,because $watch only uses for 1 element if you go array elements than watchollection is better
Hope it helpsfull.
Hi everyone I have a custom range to pick a day in angularjs. I need a listener when i pick two days (start and end) to get the values and autoamtically send this data to my rest api.
View :
<div class="form-group col-md-3 mb0" ng-if="timerange == 'custom'" id="customDiv">
<div class="row">
<label class="col-sm-3 control-label pt7">Custom</label>
<div class="col-sm-9">
<input type="text" id="customrange" name="customrange" ng-model="parent.customrange" ng-change="applyOptions()" class="form-control" ui-jq="daterangepicker" ui-options="{format: 'YYYY/MM/DD',startDate: '{{startdate}}',endDate: '{{enddate}}', maxDate:'{{enddate}}'}" />
</div>
</div>
</div>
When i click in my range dropdownbox i choose custom and then it popups a input with a date picker.. I need when i press apply to get the data.. I read a lot of documentation and cant add a listener to this... I really need to find a way...
Controller:
var rangeSelector = document.getElementsByTagName('select')[1]; //1h 24h 1w custom
if(rangeSelector.value == 'custom'){
getDate = controllerScope.getStartEndTimestamps();
var datePicker = document.getElementById("customrange").getAttribute('ui-options');
var split = datePicker.split(",");
var startDate = "";
var endDate = "";
document.getElemenstByTagName("button")[0].addEventListener("click", function(){
alert("I've changed : ");
startDate = split[1].split(': ')[1].replace(/["']/g, '');
endDate = split[2].split(': ')[1].replace(/["']/g, '');
});
console.log("range selector ",rangeSelector);
console.log("startDate ",startDate);
console.log("endDate ",endDate);
if (startDate !== undefined) {
url += '&startDate='+startDate;
}
if (endDate !== undefined) {
url += '&endDate='+endDate;
}
}
Logs:
range selector …
startDate
endDate
The problem is the alert "I've changed" dont popup... is there a simple way to do this??
In My Angular UI I want to disable a submit button if
1) All the inputs are null or empty
2) If the endDate field is less than the startDate itself
What I did is ...
<input type="submit" class="btn btn-default pull-right" style="width:100px;" value="Submit"
ng-disabled="groupMembershipUserInputForm.$invalid || !(!!groupmembership.chapterCode || !!groupmembership.groupCode ||
!!groupmembership.groupName || !!groupmembership.createdBy ||
!!groupmembership.createdDate || !!groupmembership.startDate ||
!!groupmembership.endDate || !!groupmembership.losCode
|| groupmembership.compareAgainstStartDate(groupmembership.endDate) )" />
All the strings empty/null checks are working fine except the date compare check .
In my controller the method looks like
$scope.groupmembership.compareAgainstStartDate = function (item) {
var startDate = $filter('date')(new Date($scope.groupmembership.startDate), 'MM/dd/yyyy');
var endDate = $filter('date')(new Date($scope.groupmembership.endDate), 'MM/dd/yyyy');
if (endDate < startDate) {
$scope.groupmembership.toggleInvalidInput = true;
}
else
$scope.groupmembership.toggleInvalidInput = false;
return $scope.groupmembership.toggleInvalidInput;
};
It is being hit , but I don't know why the disabling not happening if the date compare fails .
Please help me .
So first :
All the inputs are null or empty
For this just add a required to all your input/select/...
If you do so groupMembershipUserInputForm.$invalid will be true if one of the required fields is not filled.
This will simplify greatly you ng-disabled to the following :
ng-disabled="groupMembershipUserInputForm.$invalid ||
groupmembership.compareAgainstStartDate(groupmembership.endDate)"
This is a first valid working step. Now if you want to go further you could create a directive and have something like :
<input ng-model="afterDate" date-greater-than="beforeDate"/>
This will be usefull if you have other forms than need this. If you're interested to do this i suggest you to google something like "angular js custom validation form directive" and if you have trouble with that directive, after trying on your own, come back to us into another question.
FInally if you master custom validation form you could use angular-message. it's a little addon specifically designed to display error from forms.
Here is a sample code from https://scotch.io/tutorials/angularjs-form-validation-with-ngmessages :
<form name="myForm">
<input
type="text"
name="username"
ng-model="user.username"
ng-minlength="3"
ng-maxlength="8"
required>
<div ng-messages="userForm.name.$error">
<p ng-message="minlength">Your name is too short.</p>
<p ng-message="maxlength">Your name is too long.</p>
<p ng-message="required">Your name is required.</p>
<p ng-message="myCustomErrorField">Your name is <your custom reason></p>
</div>
<input type="submit" ng-disabled="myForm.$invalid"/>
</form>
Your logic pretty much right, I have doubt on your $scope.groupmembership.startDate and $scope.groupmembership.endDate because if I provide correct dates, then it is working as expected. Can you please try by providing some constant date to verify whether your function is behaving properly or not. For me it is working fine with actual date values.
$scope.startDate = $filter('date')(new Date("07/02/2016"), 'MM/dd/yyyy');
$scope.endDate = $filter('date')(new Date("0710/2016"), 'MM/dd/yyyy');
In your example dates are string type so you may not get correct result. To compare date first convert it to time using getTime() that will give you exact result. No need to use filter for date check.
just use like:
$scope.groupmembership.compareAgainstStartDate = function () {
var startDate = new Date($scope.groupmembership.startDate);
var endDate = new Date($scope.groupmembership.endDate);
if (endDate.getTime() < startDate.getTime()) {
$scope.groupmembership.toggleInvalidInput = true;
}
else
$scope.groupmembership.toggleInvalidInput = false;
return $scope.groupmembership.toggleInvalidInput;
};
Just convert startdate and enddate to milliseconds, and compare them.
Try the below code once:
$scope.groupmembership.compareAgainstStartDate = function () {
var startDate = new Date($scope.groupmembership.startDate).getTime();
var endDate = new Date($scope.groupmembership.endDate).getTime();
if (endDate < startDate) {
$scope.groupmembership.toggleInvalidInput = true;
} else {
$scope.groupmembership.toggleInvalidInput = false;
}
return $scope.groupmembership.toggleInvalidInput;
};
Good day,
I am creating a time in/timeout mechanism that sets the timeout (date and time) automatically once the user select the duration via dropdown.
here is my code:
I initialized the input box:
$('.time_in, .time_out').datetimepicker({
stepping:30
});
then trigger change with:
$('.select_book_type').change(function(){
var x = this.value;
for (var i = 0; i < time_rate.length; i++)
{
if(x == time_rate[i].id)
{
console.log(time_rate[i].rate);
var x = $(this).closest('tr');
x.find('.rate').val(time_rate[i].rate); //sets the rate of the room
//this part is my problem
var time_in = x.find('.time_in').val();
x.find('.time_out').val(time_in+time_rate[i].duration);
}
else if(x==null||x==0)
{
var x = $(this).closest('tr');
x.find('.rate').val(0);
}
}
});
supposedly Im am trying to get the value of the input with class .time_in to be used as the value to be added by my time_rate[i].duration (eg. value = 12) but whats happening is I cant get the value of .time_in so it will just set the timeout value into time_rate[i].duration (eg.12).
What I would like to accomplish:
The timeout input box should be set into time_in + duration = timeout or 09/02/2015 4:30 PM + 12 = 09/03/2015 4:30AM.
Thank you and have a good day ahead.
You need to convert both time in milliseconds before addition and then need to convert the sum into date string
var time_inMilli=new Date(time_in).getTime();
var time_outMilli = time_inMilli+(time_rate[i].duration*3600*1000);
var time_out = new Date(time_outMilli).toLocaleString();
x.find('.time_out').val(time_out);
try this
HTML
<div class="container">
<div class='col-md-5'>
<div class="form-group">
<div class='input-group date'>
<input id='datetimepicker6' type='text' class="form-control" /> <span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
JS
var MinuteToAdd = 30
$(function () {
$('#datetimepicker6').datetimepicker();
$('#datetimepicker7').datetimepicker({
useCurrent: false //Important! See issue #1075
});
$("#datetimepicker6").on("dp.change", function (e) {
$('#datetimepicker7').data("DateTimePicker").minDate(e.date);
$('#datetimepicker7').data("DateTimePicker").date(e.date.add(MinuteToAdd,'m'));
});
$("#datetimepicker7").on("dp.change", function (e) {
$('#datetimepicker6').data("DateTimePicker").maxDate(e.date);
});
});
DEMO
new to AngularJS- or the whole web development scene,
I am not even sure if this is possible or I am taking the most efficient path but I'm currently in need of a way to filter the range of dates using two input boxes, I'm using a jquery datepicker to always format the date to be "YYYY-MM-DD".
So, I have the following two input boxes,
<label class="" for="DateFromFilter">
Date From:
</label>
<input date-picker type="text" id="DateFromFilter"
class="form-control"
title="Please enter in YYYY-MM-DD format."
ng-model="search.dueDate" />
<label class="" for="DateToFilter">
Date To:
</label>
<input date-picker type="text" id="DateToFilter"
class="form-control"
title="Please enter in YYYY-MM-DD format."
ng-model="search.toDate" />
And of course I have a table with a ng-repeat directive, getting its data from a local JSON file...only the dueDate is received.
<tr> ng-repeat="dateItem in dateItems | filter:search:strict | filter:dateFilter"
<td>{{dateItem.dueDate}}</td></tr>
I need a way to let's say,
if the user selects a date on the dueDate field ONLY, the ng-repeat
list will filter and list all the dates FROM that date and onwards.
if the user selects a date on the toDate field ONLY, the ng-repeat
list will filter and list all the dates UP TO and including that
certain date.
if the user selects dates on both fields, the list will display all
the dates between those two dates.
I'm so lost on which route to take, I've been thinking I have to write a custom filter function and compare the dates with if statements and so on but I don't have a decent enough of a code to illustrate here...
any help or guidance will be greatly appreciated!
Thank you!
---------------------------------------------UPDATE-------------------------------
So I ended up trying to write a custom filter function to the best of my abilities..it does not work though....;( It kinda works if I take out the bolded conditional statements...
$scope.dateFilter = function (item) {
/*
* When the display starts, the inputs are undefined. also need to
* account for when the inputs are empty to return everything.
*/
if ((!angular.isUndefined($scope.dueDate) && $scope.dueDate != "" ) **&&
(angular.isUndefined($scope.toDate) || $scope.toDate == "" )**)
{
var inputDate = new Date($scope.dueDate);
var incomingDate = new Date(item.dueDate);
if (inputDate <= incomingDate)
{
return true;
}
else
{
return false;
}
}
else if ((!angular.isUndefined($scope.toDate) && $scope.toDate != "")**&&
(angular.isUndefined($scope.dueDate) || $scope.dueDate == "" )**)
{
var inputDate = new Date($scope.toDate);
var incomingDate = new Date(item.dueDate);
if (inputDate >= incomingDate)
{
return true;
}
else
{
return false;
}
}
else if ((!angular.isUndefined($scope.dueDate) && $scope.dueDate != "" )&&
(!angular.isUndefined($scope.toDate) && $scope.toDate != ""))
{
var inputDueDate = new Date($scope.dueDate);
var inputToDate = new Date($scope.toDate);
if (inputDueDate < item.dueDate && inputToDate > item.dueDate )
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
};
Are you familiar with angular bootstrap UI?
http://angular-ui.github.io/bootstrap/
There is an extension that might be what you are looking for here: http://eternicode.github.io/bootstrap-datepicker/
Instead of using a repeated list of dates you could use a date picker to display the available dates. As I think it might be easier to implament.
Edit:
Otherwise you could write a date range filter to handle this functionality. This might be a good place to start
https://gist.github.com/Voles/5459410
useage: ng-repeat="... | daterage:start:end"
I am on my phone so am unable to give you an implementation at this time. Another user may be able to oblige.
Custom filter used to display dates between the selected dates from json or array
var app = angular.module("myApp",[])
.directive("datepicker1",function(){
return{
restrict:"A",
link:function(scope,el,attr){
el.datepicker({
dateFormat:'yy-mm-dd'
});
}
};
})
.directive("datepicker2",function(){
return{
restrict:"A",
link:function(scope,el,attr){
el.datepicker({
dateFormat:'yy-mm-dd'
});
}
};
})
.filter('myFilter',function(){
return function(items, fromdate,todate){
var arrayReturn = [];
items.forEach(function(val,i){
var a = new Date(items[i].cdet.cdate.date);
console.log(a)
console.log(fromdate)
//var yy = a.getFullYear();
//var mm = a.getMonth()+1;
//var dd = a.getDate();
var myDate = a;
var fr = new Date(fromdate);
var to = new Date(todate);
if(myDate >= fr && myDate <= to){
arrayReturn.push(items[i]);
}
});
return arrayReturn;
}
})
.controller('myCtrl',function($scope){
$scope.startdate = "2017-10-18";
$scope.enddate = "2019-1-28"
$scope.names = [
{
"cname" : "A",
"cdet":{
cdate:{
date:"2018-5-15"
}
}
},
{
"cname" : "B",
"cdet":{
cdate:{
date:"2017-5-20"
}
}
},
{
"cname" : "C",
"cdet":{
cdate:{
date:"2019-5-13"
}
}
},
{
"cname" : "D",
"cdet":{
cdate:{
date:"2018-10-2"
}
}
},
{
"cname" : "E",
"cdet":{
cdate:{
date:"2018-12-8"
}
}
}
];
});
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.min.css" rel="stylesheet"/>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
From Date:<input type="text" datepicker1 ng-model="startdate"/>
To Date:<input type="text" datepicker2 ng-model="enddate"/>
<ul ng-repeat="name in names | myFilter:startdate:enddate">
<li><span>{{ name.cname }}</span> | <span>{{ name.cdet.cdate.date }}</span></li>
</ul>
</div>