Angular bootstrap datepicker isnt loading in a separate screen - angularjs

I have a date picker in one screen/url (in the same app) where the template works and loads properly but now in a different screen/url (in the same app) the date picker doesnt display properly. It looks like:
Ive compared both codes from both screens and its not working..
function dateFilter() {
var directive = {
controller: dateFilterController,
controllerAs: 'vm',
bindToController: true,
restrict: 'E',
templateUrl: 'app/utils/directives/date-filter/date.filter.tpl.html',
scope: {
'popup': '=',//date format
'options': '=',//uib-datepicker options
'ngModel': '=',//selected date
'ngChange': '=',//filter function
'myId': '=',//id and name of uib-datepicker
'label': '=',//label that preceeds datepicker
'name': '=',//name of the property being filtered
'minDate': '=',//the minumum acceptable date
'maxDate': '=',//the maximum acceptable date,
'updateQuery': '=',
'query': '=',
'popupUrl': '='
}
};
return directive;
}
function dateFilterController() {
var vm = this;
vm.dateChanged = function (date) {
var newFilterValue = {
query: vm.query,
value: date
};
vm.updateQuery(newFilterValue);
};
vm.applyDateFilter = function (x) {
vm.dateChanged(x);
var from = true;
//If the label ends in to, that means we are filtering on the to date.
if (vm.label.substring(vm.label.length - 2, vm.label.length) === 'to') {
from = false;
}
//format the filter data in a way so it can be interpretted by ngChange
var temp = {
key: vm.name,//The name of the property being filtered
value: x,//The value from the filter
from: from//Boolean indicating if it is the to(false) or from(true) date.
};
vm.ngChange(temp);
};
vm.isOpen = false;
vm.ngClick = function () {
vm.isOpen = true;
};
}
This is the date filter tpl
<div class="date_input">
<label for="{{vm.myId}}">{{ vm.label | translate}}</label>
<input tabindex="0"
role="button"
aria-labelledby="fromToDescription"
id="{{vm.myId}}"
name="{{vm.myId}}"
type="text"
class="form-control"
uib-datepicker-popup="{{vm.popup}}"
datepicker-options="vm.options"
datepicker-popup-template-url="{{vm.popupUrl}}"
placeholder="mm/dd/yyyy" ng-pattern="/^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(20)\d{2}$/"
autocomplete="off"
ng-model="vm.ngModel"
is-open="vm.isOpen"
show-button-bar="false"
ng-change="vm.applyDateFilter(vm.ngModel)"
ng-click="vm.ngClick($event)"
minDate="vm.minDate"
maxDate="vm.maxDate"
/>
</div>
html where I used the directive.
<!-- FROM DATE -->
<date-filter
popup="$ctrl.formats"
options="$ctrl.dateOptions"
ng-model="$ctrl.fromDate"
ng-change="$ctrl.filterFunction"
name="customFromDate"
label="$ctrl.fromVerbiage"
min-date="$ctrl.dateOptions.minDate"
max-date="$ctrl.dateOptions.maxDate"
my-id="customFromDate"
update-query="$ctrl.updateQuery"
query="customFromDate"
popup-url="$ctrl.popupTpl"
></date-filter>
<div> <!-- TO DATE -->
<date-filter
popup="$ctrl.formats"
options="$ctrl.dateOptions"
ng-model="$ctrl.toDate"
ng-change="$ctrl.filterFunction"
name="customToDate"
label="$ctrl.toVerbiage"
min-date="$ctrl.dateOptions.minDate"
max-date="$ctrl.dateOptions.maxDate"
my-id="customToDate"
update-query="$ctrl.updateQuery"
query="customToDate"
popup-url="$ctrl.popupTpl"
></date-filter>
</div>

Related

How to get value of chcecked checkbox - angularJS

J started learn Angular and I have trouble with getting value of checkboxes.
<label ng-repeat="role in groupsapp">
<input type="checkbox" ng-click="selectedRole([role.name,role.id,????])">{{role.name}}</label>
How get value checked/unchecked in place "???"
I found also:
ng-true-value="{{role.id}}_{{role.name}}_true"
ng-false-value="{{role.id}}_{{role.name}}_false"
but I don't know how to get this value of checkbox, anyone can help ?
to get it working with angular you need to add the ng-model directive to your input so angular will process it.
<label ng-repeat="role in groupsapp">
<input ng-model="role.value" type="checkbox" ng-click="selectedRole([role.name,role.id,role.value])">{{role.name}}
</label>
I guess you might have got your answer but still if in case in future if you want to use multiple check boxes and need to collect what all items are collected you can use a custom directive.Here is a link on how to use it.
Below is sample code snippet in HTML
<body ng-app="mainApp" ng-controller="MainCtrl">
<h1>Multi Check box</h1>
<multi-checkbox selectedlist="req.selectedList" orginallist="req.sourceList" value="code" label="desc" all="true" sort-by="desc"></multi-checkbox>
<pre ng-cloak>{{req.selectedList |json}}</pre>
</body>
This requires a source list(orginallist) and a destination list(selectedlist) where selected values should go,it also sorts the list as per your need.
Just add this directive in your JS file
mainApp.directive('multiCheckbox', ['$log', '$filter', '$timeout', function($log, $filter, $timeout) {
return {
restrict: 'EA',//E-element & A - attribute
template:
'<div> <div ng-show="checkbox.showAll" class="checkbox"> ' +
'<label style="font-size: 12px"> <input type="checkbox" ' +
'id="all" name="all" ng-model="checkbox.all" ' +
'ng-checked="checkbox.all" ng-change="selectAll()" /> All ' +
'</label> ' +
'</div>' +
'<div ng-repeat="item in list track by $index "class="checkbox"> ' +
'<label style="font-size: 12px"> <input type="checkbox" ' +
'id="{{item.value}}" name="{{item.label}}" ' +
'ng-checked="item.checked" ng-click="$parent.toggle($index)"/> {{item.label}}' +
'</label>' +
'</div> </div>',
replace: true, //to replace our custom template in place of tag <multi-checkbox>
transclude: false,//make it true if we want to insert anything btw directive tags
scope: { //isolate scope created
selectedlist: '=',
orginallist: '=',
value: '#',
label: '#',
all: '#',
sortBy: '#'
},
link: function($scope, element, attrs) {
$scope.checkbox = {};
$scope.checkbox.all = false; //set 'All' checkbox to false
$scope.checkbox.showAll = $scope.all == 'true' ? true : false;//to show/hide 'All' checkbox
//function called on click of check box
$scope.toggle = function(index) {
var item = $scope.list[index];
var i = $scope.selectedlist.length > 0 ? $scope.selectedlist.indexOf(item.value) : -1;
item.checked = !item.checked;
if (!item.checked) {
$scope.selectedlist.splice(i, 1);//remove item if unchecked
$scope.checkbox.all = false;//make 'All' to uncheck too
} else if (item.checked) {
$scope.selectedlist.push(item.value);//add item if checked
}
};
//function called when 'All' checkbox is checked
$scope.selectAll = function() {
var totalList = $scope.list;
$scope.selectedlist = [];
//if selected add all items
//if unchecked remove all items from selected list
angular.forEach(totalList, function(item) {
item.checked = $scope.checkbox.all;
if (item.checked) {
$scope.selectedlist.push(item.value);
} else {
$scope.selectedlist = [];
}
});
};
//always watch my source list if it has been modified and update back..
$scope.$watch('orginallist', function(value) {
//sort accordingly..
value = $filter('orderBy')(value, $scope.sortBy);
$scope.list = [];
if (angular.isArray(value)) {
angular.forEach(value, function(item) {
$scope.list.push({
value: item[$scope.value],
label: item[$scope.label],
checked: item.checked
});
});
}
}, true);
//clear 'All' checkbox value if all items are de selected
$scope.$watch('selectedlist', function(value) {
if (!angular.isArray(value) || (angular.isArray(value) && value.length <= 0)) {
$scope.checkbox.all = false;
}
}, true);
}
};
}]);

Angular Typeahead box is showing way above search field

The results for my typeahead search are showing way above the actual input field. The Company Name field is where my actual input is but the results are way north of that.
Here's my code. Anyone know what I'm doing wrong?
<span ng-switch-when="typeahead">
<input type="text"
class="form-control"
placeholder="Search..."
typeahead="option.value as option.displayValue for option in formField.options | filter:$viewValue | limitTo:3"
ng-model="formModel[formField.field.columnName]" />
</span>
Controller:
(function(angular){
"use strict";
var module = angular.module('xdock.formField',[]);
module.constant('FORM_FIELD_TYPES', ["text", "number", "date", "lookup", "check", "timepicker", "typeahead"]);
module.directive('formField',[
function formField() {
return {
scope: {
formField: '=',
formLabel: '#',
formModel: '=',
formErrorModel: '='
},
templateUrl: 'common/formField.html',
link: function postLink(scope) {
scope.flags = {datepickerOpen : false};
scope.datepickerOptions = {
showButtonBar: false
};
scope.openDatepicker = function openDatepicker($evt) {
$evt.preventDefault();
$evt.stopPropagation();
scope.flags.datepickerOpen = true;
};
function formatDate() {
if(scope.formField.type === "date" && scope.formModel[scope.formField.field.columnName]) {
scope.formModel[scope.formField.field.columnName] =
new Date(scope.formModel[scope.formField.field.columnName]);
}
}
formatDate();
}
};
}
]);
}(window.angular));

AngularJS - set validity of wrapped directives

I'm working on a simple directive - date/time picker. It wraps angular material datepicker and two additional selects (for hours and minute), builds the date and exposes it via ngModel.
I have implemented validation logic, where user can supply min and max value, and if the selected date and time falls outside range, model validity is set to false.
Here is the markup of the directive and it's code:
<div layout="column">
<div layout="row">
<md-datepicker name="selectedDatePicker" ng-model="selectedDate" flex="50" flex-order="1"></md-datepicker>
<md-input-container flex="25" flex-order="2">
<label>Hour</label>
<md-select ng-model="selectedHour">
<md-option ng-repeat="hour in hours" value="{{hour}}">
{{hour}}
</md-option>
</md-select>
</md-input-container>
<md-input-container flex="25" flex-order="2">
<label>Minute</label>
<md-select ng-model="selectedMinute">
<md-option ng-repeat="minute in minutes" value="{{minute}}">
{{minute}}
</md-option>
</md-select>
</md-input-container>
</div>
<div layout="row">
<ng-transclude></ng-transclude>
</div>
</div>
angular.module('myApp')
.directive('jcdatetimepicker', function ($parse) {
var link = function (scope, iElement, iAttrs, ngModel) {
var initValue = scope.ngModel;
setDateTime(initValue);
ngModel.$parsers.push(validateInput);
ngModel.$formatters.push(validateInput);
ngModel.$render = function () {
setDateTime(ngModel.$viewValue);
}
scope.$on('jcdatetimepicker:updateModel', function (evt, args) {
ngModel.$setViewValue(validateInput(args));
});
function validateInput(inputDate){
var valid = true;
if (angular.isDefined(scope.minValue) && (inputDate < scope.minValue)) {
valid = false;
ngModel.$setValidity('min', false);
}
else {
ngModel.$setValidity('min', true);
}
if (angular.isDefined(scope.maxValue) && (inputDate > scope.maxValue)) {
valid = false;
ngModel.$setValidity('max', false);
}
else {
ngModel.$setValidity('max', true);
}
return valid ? inputDate : undefined;
}
function setDateTime(date) {
if (angular.isDate(date)) {
scope.selectedMinute = date.getMinutes();
scope.selectedHour = date.getHours();
scope.selectedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
}
}
};
return {
restrict: 'E',
replace: false,
transclude: true,
require: '^ngModel',
scope: {
ngModel: '=ngModel',
minValue: '=min',
maxValue: '=max'
},
controller: 'jcDateTimePickerController',
link: link,
templateUrl: 'templates/shared/jcDateTimePicker/jcDatetimePicker.html'
}
}).controller('jcDateTimePickerController', function ($scope, $element) {
$scope.hours = [];
$scope.minutes = [];
$scope.selectedMinute = 0;
$scope.selectedHour = 12;
$scope.selectedDate = new Date();
$scope.isValid = false;
//initialize hours & minutes
function init() {
for (var h = 0; h < 24; h++) {
$scope.hours.push(h);
}
for (var m = 0; m < 60; m++) {
$scope.minutes.push(m);
}
};
init();
$scope.$watchGroup(['selectedMinute', 'selectedHour', 'selectedDate'], function (newVals, oldVals, _scope) {
var minutes = newVals[0];
var hours = newVals[1];
var date = newVals[2];
date.setHours(hours, minutes, 0);
$scope.$broadcast('jcdatetimepicker:updateModel', date);
});
});
It works fine when it comes to validation - ngModel validity of model passed to my directive is set correctly. The problem is, that when the selected value is not valid, I would like also to set validity on the directives that my directive is wrapping mdDatepikcer and mdSelect - so that UI of those directives will also indicate invalid input.
However I have no clue how to grab those wrapped directives, e. g. date picker and tinker with it's validity. In unit tests, I tried with isolated scope, but selectedDatePicker was undefined.
Is that even possible? Or is it possible to get it's ngModel controller, and set validity that way?
Any advice is highly appreciated.
if you have the signature of the scopes of the mdDatepicker and mdSelect, you can use: angular.element($("[name='selectedDatePicker']")).scope, then call the function(s) or set properties that's necessary to give up the behavior you want.
I haven't tried the code but that's one possible way.

Making AngularUI datepicker an actual directive

I'm trying to turn angular-ui's date-picker into an actual directive.
I can display it on the page with the correct model and format, but the toggling doesn't work for me (trying to name it via the attributes).
Here is my code:
My html
<date-picker data-format="dd/MM/yyyy" data-model-name="dateReviewed" data-ng-model="oneWMS.dateReviewed" data-status="statusDateReviewed" data-opened="openDateReviewed"></date-picker>
My directive
function datePicker() {
return {
restrict: 'AE',
require: 'ngModel',
scope: {
format: '#',
mod: '=ngModel',
status: '#',
opened: '#'
},
template: '<div class="input-group">' +
'<input type="text" class="form-control" datepicker-popup="{{format}}" data-ng-model="mod" is-open="status.opened" ng-required="true" close-text="Close" />' +
'<span class="input-group-btn">' +
'<button type="button" class="btn btn-default" ng-click="opened($event)"><i class="glyphicon glyphicon-calendar"></i> </button>' +
'</span>' +
'</div>',
link: function(scope, iElement, iAttrs) {
// all the directive code
console.log(iAttrs.format); // dd/MM/yyyy
console.log(iAttrs.ngModel); // oneWMS.dateReviewed
console.log(iAttrs.status); // statusDateReviewed
console.log(iAttrs.opened); // openDateReviewed
console.log(iAttrs.modelName); // dateReviewed
var modelStatusDate = iAttrs.status;
var modelOpenDate = iAttrs.opened;
var modelName = iAttrs.modelName;
scope.today = function() {
scope.modelName = new Date();
scope.dateApproved = new Date();
scope.today();
scope.clear = function () {
scope.modelName = null;
};
scope.modelOpenDate = function($event) {
scope.modelStatusDate.opened = true;
};
scope.modelStatusDate = {
opened: false
};
scope.getDayClass = function(date, mode) {
if (mode === 'day') {
var dayToCheck = new Date(date).setHours(0,0,0,0);
for (var i=0;i<scope.events.length;i++){
var currentDay = new Date(scope.events[i].date).setHours(0,0,0,0);
if (dayToCheck === currentDay) {
return scope.events[i].status;
}
}
}
return '';
};
} // link
} // return
} // picker
}
Don't know if just opening the picker doesn't work or if the date selecting will fail as well.
I have made a custom date directive using angularui date-picker. Have a look, it might be useful to you. Here is plunkr url . http://plnkr.co/edit/FDigEjyMYm5SVYnQyZGp.
If you're using Angular and Bootstrap, I would strongly encourage you to use Angular UI Bootstrap.
The other Angular UI libraries are not actively maintained.

How to create angularjs custom directive for google location

I'm trying to create a directive to lookup google locations using <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&libraries=places&language=en-US"></script> like this:
angular.module('MyApp').directive('locationPicker', function () {
return {
restrict: 'AE',
replace: true,
require: 'ngModel',
template: '<input id="{{id}}" type="text" class="{{class}}" placeholder="{{placeholder}}" />',
scope: {
id: '#',
class: '#',
placeholder: '#',
},
link: function ($scope, elm, attrs, controller) {
var autocomplete = new google.maps.places.Autocomplete(elm[0], {types: ['geocode']});
var componentForm = {
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name'
};
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
var lat = place.geometry.location.lat();
var lng = place.geometry.location.lng();
var name = "";
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
if (name !== "") {
name += ", ";
}
var val = place.address_components[i][componentForm[addressType]];
name += val;
}
}
elm[0].value = name;
$scope.$apply(function () {
controller.$setViewValue({name: name, lat: lat, lng: lng});
});
});
}
};
});
And my input:
<input id="location" location-picker ng-model="location" class="form-control" placeholder="Project location" ng-required="true" />
In my controller:
$scope.location = {
name:null,
lat:null,
lng:null
};
Everything looks fine but when my component is first rendered, the value of the input is [Object object] instead of the place holder (Project Location).
What am I doing wrong?
Problem
You are binding ngModel to the location object, which renders as [object Object] when coerced to a string.
Solution
Since you are grabbing hold of the NgModelController in your directive, you can use its $formatters pipeline to transform the model value (location object with name, lat, lng properties) into the view value and the $render function to specify how to render the value if it is changed outside of the ngModel lifecycle.
Here is a working plunker: http://plnkr.co/edit/5HPFelbDFUrzeccGfgYx?p=preview. The crucial piece of code is
// triggered by $setViewValue
controller.$formatters.push(function (value) {
return value ? value.name : value;
});
// triggered by clear() from controller
controller.$render = function () {
input.value = controller.$modelValue.name;
};
I have also made the following modifications to your code:
Used location-picker as an element directive. input is not a good choice of element since it already has bindings to ngModel.
Removed replace: true. It is a deprecated configuration option in directives, and can cause some strange behaviors, since it tries to mix attributes of directive element and attributes of template element.
Removed elm[0].value = name;. This is handled by the lifecycle of the ngModel when you call $setViewValue.

Resources