Implementing ng-change With Angularjs Custome Directive - angularjs

I have Following Directive , how can i implement ng-change with it . the directive is working but ng-change only works when i manually change value of text box not when i change it using date picker
app.directive('datepicker', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
$(function () {
element.persianDatepicker({
formatDate: "YYYY/0M/0D",
onSelect: function (date) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(date);
});
}
});
});
}
}
});
and in my HTML
<input datepicker type="text" id="EndDate" ng-model="Filter.EndDate" class="form-control" ng-change="DateSelect()" />
DateSelect() only runs when i change value of text box manually

Edited
ng-change is directive only for user input. Try to use $watch instead. Here are good answers:
Angular - ng-change not firing when ng-model is changed
When to use $watch or ng-change in Angularjs

Related

Angular attribute directive add ng-change

I have a directive defined as:
module.directive('inputChanged', function () {
function link(scope, element, attrs) {
var field = attrs.ngModel;
if (field) {
var fn = "model.changed('" + field + "')";
element.attr('ng-change', fn);
}
}
return {
restrict: 'A',
link: link
}
});
which I am using like:
<input ng-model="model.user.middleName" input-changed type="text" class="k-textbox">
The goal is to dynamically inject the ng-change with the model field as parameter. My scenario is actually a bit more complex, but I am simplifying it for this question. This is why I need to inject it dynamically and not place it directly in the input markup.
This works and I can see the ng-change in the markup once the page is rendered.
<input ng-model="model.user.middleName.value" type="text" class="k-textbox ng-valid ng-not-empty ng-dirty ng-valid-parse ng-touched" ng-change="model.changed('model.user.middleName.value')" aria-invalid="false">
The problem is that model.changed(...) is not firing. If I hardcode it instead of using the directive, everything works as expected.
What am I missing?
Thank you.
You need to compile the element after adding the ng-change directive.
angular
.module('app')
.directive('inputChanged', inputChanged);
function inputChanged($compile) {
var directive = {
restrict: 'A',
link: link,
terminal: true,
priority: 1000,
};
return directive;
function link(scope, element, attrs) {
var field = attrs.ngModel;
if (field) {
var fn = "main.changed(" + field + ")";
// Remove the attribute to prevent
// an infinite compile loop
element.removeAttr('input-changed');
element.attr('ng-change', fn);
$compile(element)(scope);
}
}
};
Working plunker.
More information about adding directives from a directive in this post.

angular directive was only called once

I am using a directive to build a custom validator and it works fine. But, it was called only once! If my "roleItems" are updated, this directive was not called again! How can it be called every time when "roleItems" are updated?
Here are the markups. And "Not-empty" is my directive.
<form name="projectEditor">
<ul name="roles" ng-model="project.roleItems" not-empty>
<li ng-repeat="role in project.roleItems"><span>{{role.label}}</span> </li>
<span ng-show="projectEditor.roles.$error.notEmpty">At least one role!</span>
</ul>
</form>
This is my directive. It should check if the ng-model "roleItems" are empty.
angular.module("myApp", []).
directive('notEmpty', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$validators.notEmpty = function (modelValue, viewValue) {
if(!modelValue.length){
return false;
}
return true;
};
}
};
});
Main purpose of validator is validate ngModel value of user input or model change, so it should be uset to checkbox/textara/input and etc. You cant validate ng-model of everything. Angular is enough intelligent to knows that ng-model makes no sens so he is just ignoring it .
I you wanna change only error message you can check it via .length property. If you wanna make whole form invalid , i suggest you to make custom directive , put it on , and then in validator of this directive check scope.number.length > 0
Basically just adjust your directive code to input element and hide it .... via css or type=hidden, but dont make ngModel="value" its not make sense because ng-model is expecting value which can be binded and overwriteen but project.roleItems is not bindable! so put ng-model="dummyModel" and actual items to another param ...
<input type="hidden" ng-model="dummyIgnoredModel" number="project.roleItems" check-empty>
angular.module("myApp", []).
directive('checkEmpty', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$validators.push(function (modelValue, viewValue) {
if(!scope.number.length){
return false;
}
return true;
});
//now we must "touch" ngModel
scope.$watch(function()
{
return scope.number
}, function()
{
ctrl.$setViewValue(scope.number.length);
});
}
};
});

AngularJS - ui-date textbox editable

I am using ui-date in AngularJS.
<input name="dateofbirth" id="dateofbirth" type="text" ng-model="search.dateofbirth" ui-date="dateOptions" ui-date-format="mm/dd/yy">
When I click on the textbox, a calendar pops up, but the user cannot type in the textbox.
How can I make this textbox editable?
You can use this directive, when you click on the text field calendar should be shown.. Here is the working fiddle
http://jsfiddle.net/nabeezy/HB7LU/209/
myApp.directive('calendar', function () {
return {
require: 'ngModel',
link: function (scope, el, attr, ngModel) {
$(el).datepicker({
dateFormat: 'yy-mm-dd',
onSelect: function (dateText) {
scope.$apply(function () {
ngModel.$setViewValue(dateText);
});
}
});
}
};
})

Auto focus on input filed in angular js

I have created a directive for auto focus on text box
(function () {
'use strict';
angular.module('commonModule').directive('srFocuson',function(){
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs) {
scope.$watch(attrs.focusMe, function (value) {
if (value === true) {
console.log('value=', value);
element[0].focus();
scope[attrs.focusMe] = false;
}
});
}
};
});
})();
And now i want to bind that directive to my text box.I have tried to bind to input field but its not working.
<input placeholder="SR ID, SSN/ITIN, or School ID" sr-focuson="focusMe" type="text"
id="form_ID" name="searchId" autofocus
data-ng-model="vm.searchCriteria.searchId"
maxlength="20" class="form-control">
http://plnkr.co/edit/A39duXhGvCedAaVuB3uQ?p=preview
I made working fiddle with your idea. http://jsfiddle.net/fLaAG/
It's sort of unclear where you would be updating scope.focusMe so I made an explicit button that would set that value to true.
<button type="button" ng-click="Focus()" type="button">Focus</button>
...
$scope.Focus = function() {
$scope.focusMe = true;
};
Also I'm setting up an isolate scope, so I can just watch string I give it.
scope: {
focusMe: '=focusOn'
},
Hope this helps
Here is a method using built-in angular functionality, dug out from the murky depths of the angular docs. Notice how the "link" attribute can be split into "pre" and "post", for pre-link and post-link functions.
Working Example: http://plnkr.co/edit/Fj59GB
// this is the directive you add to any element you want to highlight after creation
Guest.directive('autoFocus', function() {
return {
link: {
pre: function preLink(scope, element, attr) {
console.debug('prelink called');
// this fails since the element hasn't rendered
//element[0].focus();
},
post: function postLink(scope, element, attr) {
console.debug('postlink called');
// this succeeds since the element has been rendered
element[0].focus();
}
}
};
});
<input value="hello" />
<!-- this input automatically gets focus on creation -->
<input value="world" auto-focus />
Full AngularJS Directive Docs: https://docs.angularjs.org/api/ng/service/$compile

Dialog does not get the focus after it opens (angularJS)

I am calling the following from a button:
var d = $dialog.dialog({dialogFade: false, modal:true, backdropClick: false});
d.open('html/xyz.html', 'xyzController');
All work fine except the dialog does not get the focus. it treats it as an element at the end of the page if we TAB.
is there a way to give the dialog the focus??? I tried all solution I can find but no success.
thanks
You can use a directive to setFocus on any element:
MyApp.directive('CustomSetFocus', [function () {
return {
restrict: 'A',
link: function (scope, element, attrs, controller) {
scope.$watch(attrs.customSetFocus, function (newValue, oldValue) {
if (newValue === true) {
element[0].focus();
}
});
}
};
}]);
Then you can trigger it like so:
<input type="text" id="whatever" custom-set-focus="true"/>
Or, you can set a scope variable in your controller that will trigger the focus, maybe in an intialize() function or something like that:
<input type="text" id="whatever" custom-set-focus="someScopeVariable"/>

Resources