Please, tell me how to describe a directive 'myValidation' for input-field
<input my-validation ng-model="myValue">
to make it behave as follows:
if user inputs 'A' directive must change myValue to 'B' (showing it in input field)
otherwise just remain original value
You can create a watch on myValue and perform your validation when the value is changed...
angular.module('App', [])
.directive('myValidation', function () {
return {
restrict: 'A',
require: "ngModel",
link: function (scope, element, attrs, ngModel) {
scope.$watch(function () {
return ngModel.$modelValue;
}, function (newVal, oldVal) {
if (newVal === 'A') {
scope.myValue = 'B';
}
});
}
};
});
Fiddle: http://jsfiddle.net/fMTVm/1/
Related
I am trying to use a $scope.quickText(data) function in my controller. The function reviews the parameter 'data' and looks for any codes (ie: .smoke) and then adds that text to the value of the model.
For instance, if the ngModel value was "Completed smoke assessment" and someone types into the 'textarea' or 'text' input .smoke, it would add "patient smokes. Completed smoke assessment". This would be available to see in the view instantly as the user is typing .smoke. The function works but my directive does not.
myApp.directive('gmaEvalQuickText1', ['$timeout', function ($timeout) {
'use strict';
return {
restrict: 'A',
require: 'ngModel',
scope: {
quickTextEvaluate: '&',
},
bindToController: true,
controller: 'gmaController',
controllerAs: 'gc',
link: function ($elem, $ctrl,controller) {
$elem.on('input keyup change', function () {
var val = $elem.val().toString();
var newVal = gc.quickText(val).toString();
$ctrl.$setViewValue(newVal);
$timeout(function () {
$ctrl.$render();
});
});
}
}
}]);
I am very new to AngularJS so I am sure I am doing something wrong.
I figured out how to make it work :)
For those who need the answer:
Directive:
myApp.directive('evalQuickText', ['$timeout', function ($timeout) {
'use strict';
return {
restrict: 'A',
require: 'ngModel',
scope: {
quicktextevalfct: '='
},
link: function ($scope, $elem, attrs, $ctrl) {
$elem.on("keydown keypress", function (event) {
if(event.which === 13) {
var val = $elem.val().toString();
var newVal = $scope.quicktextevalfct(val);
$ctrl.$setViewValue(newVal + "\n");
$timeout(function () {
$ctrl.$render();
});
event.preventDefault();
}
if(event.which === 9) {
var val = $elem.val().toString();
var newVal = $scope.quicktextevalfct(val);
$ctrl.$setViewValue(newVal);
$timeout(function () {
$ctrl.$render();
});
event.preventDefault();
}
});
}
};
}]);
HTML:
eval-quick-text quicktextevalfct="quickTextEvaluate"
I'm trying to fill a form with existing values using the controller $scope to pass those to the DOM.
Now, I'm using a directive to read and write values in a specific select menu (where I use bootstrap form helpers) menu:
app.directive('currencypicker', function () {
return {
restrict: 'A',
require: '?ngModel',
scope: {
ngModel: '='
},
link: function (scope, elem, attrs, ctrl) {
elem.addClass('bfh-currencies');
elem.addClass('bfh-selectbox');
elem.bfhselectbox({
filter: (elem.attr('data-filter') == 'true') ? true : false
}).on('change.bfhselectbox', function() {
return scope.$apply(function () {
return scope.ngModel = elem.val();
});
});
return elem.bfhcurrencies({
flags: (elem.attr('data-flags') == 'true') ? true : false,
currency: scope.ngModel || 'EUR'
});
}
};
});
Here the HTML snippet
<div currencypicker id="cost-currency" data-flags="true" data-filter="true" ng-model="newEvent.cost_currency"></div>
The problem is that when I try to assign my model value to currency attribute with scope.ngModel it evaluates always to undefined and so 'EUR' value is assigned, I checked my scope with firebug, where ngModel value is "GBP".
I can't figure out why it happens.
The way you have to use your directive is the following :
app.directive('currencypicker', function () {
return {
restrict: 'A',
require: '?ngModel',
//template : you have no template nor url template?
link: function (scope, elem, attrs, ngModelCtrl) {
// You can have your "ngModelValue" into ngModelCtrl.$viewValue
// Also, you now have access to all the functions declared into ngModelController
}
};
});
And if you want more information on that topic, do not hesitate to have a look at the doc : https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
I have the following code:
<div id='parent'>
<div id='child1'>
<my-select></my-select>
</div>
<div id='child2'>
<my-input></my-input>
</div>
</div>
I also have two directives which get some data from the data factory. I need the two directives to talk to each other such that when a value in select box is changed the input in changes accordingly.
Here's my two directives:
.directive("mySelect", function ($compile) {
return {
restrict: 'E',
scope:'=',
template: " <select id='mapselectdropdown'>\
<option value=map1>map1</option> \
<option value=map2>map2</option> \
</select>'",
link: function (scope, element, attrs) {
scope.selectValue = //dont konw how to get the value of the select
}
};
})
.directive("myInput", function($compile) {
return {
restrict: 'E',
controller: ['$scope', 'dataService', function ($scope, dataService) {
dataService.getLocalData().then(function (data) {
$scope.masterData = data.input;
});
}],
template: "<input id='someInput'></input>",
link: function (scope, element, attrs) {
//here I need to get the select value and assign it to the input
}
};
})
This would essentially do the onchange() function that you can add on selects. any ideas?
You could use $rootScope to broadcast a message that the other controller listens for:
// Broadcast with
$rootScope.$broadcast('inputChange', 'new value');
// Subscribe with
$rootScope.$on('inputChange', function(newValue) { /* do something */ });
Read Angular docs here
Maybe transclude the directives to get access to properties of outer scope where you define the shared variable ?
What does this transclude option do, exactly? transclude makes the contents of a directive with this option have access to the scope outside of the directive rather than inside.
-> https://docs.angularjs.org/guide/directive
After much research this is what worked...
I added the following:
.directive('onChange', function() {
return {
restrict: 'A',
scope:{'onChange':'=' },
link: function(scope, elm, attrs) {
scope.$watch('onChange', function(nVal) { elm.val(nVal); });
elm.bind('blur', function() {
var currentValue = elm.val();
if( scope.onChange !== currentValue ) {
scope.$apply(function() {
scope.onChange = currentValue;
});
}
});
}
};
})
Then on the element's link function I added:
link: function (scope, elm, attrs) {
scope.$watch('onChange', function (nVal) {
elm.val(nVal);
});
}
Last added the attribute that the values would get set to in the scope:
<select name="map-select2" on-change="mapId" >
So I know that I can have the model be different than the view value by using $parsers.
But what if I want to have the model change, without using $parsers?
For example:
html
<input tel-input ng-model="data.phone">
{{data.phone}}
js
.directive('telInput', function($compile) {
return {
restrict: 'A',
scope: {
ngModel: '='
},
link: function(scope, elem, attrs) {
elem.on('paste', function() {
scope.ngModel = 'special model value after pasting';
});
}
};
});
The problem with this is that when scope.ngModel = 'pasting not allowed occurs, it changes the value in the input.
With $parsers, it changes the value in the model, but the view value remains the same.
There isn't any $setModelValue method, which seems like it would serve this purpose.
Any ideas?
Try this,
.directive('telInput', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
elem.on('paste', function() {
ngModel.$setViewValue('special model value after pasting');
ngModel.$render();
});
}
};
});
I'm trying to create an app where I poll live data every 10 seconds or so. And if the data changes it should get highlighted in the view. I have successfully managed this, but with a little help from jQuery. I want to do it with a template in angular instead.
This is my controller:
angular.module('myApp.controllers', [])
.controller('MainCtrl', ['$rootScope', 'liveDataPoller', function($rootScope, liveDataPoller) {
$rootScope.liveData = liveDataPoller.getData();
}]);
This is my directive:
angular.module('myApp.directives', []).
directive('liveValue', function() {
return {
restrict: 'A',
scope: {
val: '='
},
link: function(scope, element, attrs) {
scope.$watch('val', function(newValue, oldValue) {
if(newValue && oldValue && (newValue !== oldValue)) {
if(newValue < oldValue) {
element.removeClass("up").addClass("down");
} else {
element.removeClass("down").addClass("up");
}
} else {
element.removeClass("down").removeClass("up");
}
});
}
}
});
This is my view:
<div live-value val="liveData.randomInteger">{{liveData.randomInteger}}</div>
Is it possible to have the add/remove class changed to use transclude and a template instead? Don't really want to mix jQuery in this.
Just let me know if anything is unclear.
Sample demo: http://plnkr.co/edit/uXhOceXYWLLkmRkzxx1h?p=preview
A scope variable can be used to track the new changes and use a two way binding to update the class in the html.
app.directive('liveValue', function() {
return {
restrict: 'E',
replace: true,
scope: {
data: '=', change:'='
},
template: '<div class="{{change}}">The value({{data}}) has gone: {{change}}</div>',
link: function(scope, element, attrs) {
scope.change = '';
scope.$watch('data', function (newValue, oldValue) {
if (newValue == oldValue) {
scope.change='nochange';
}else if(newValue<oldValue){
scope.change='down';
}else{
scope.change='up';
}
});
}
}
});