How can i bind model in angular directive - javascript

I am using angular type ahead from here
http://pineconellc.github.io/angular-foundation/#/typeahead
I have made a directive where template is
<div>
<input type="text"
ng-model="user.selected"
placeholder="Type to select . . ."
typeahead="item as item.name for item in getData($viewValue)"
typeahead-loading="loadingData"
class="form-control">
<i ng-show="loadingData" class="glyphicon glyphicon-refresh"></i>
</div>
and directive is
return {
restrict: 'AE',
replace: true,
scope: true,
templateUrl: 'type.html',
link: function (scope, elem, attrs) {
var url = window.location.origin + attrs.url;
scope.getData = function (val) {
return $http.get(url, {
params: {
q: val
}
}).then(function (response) {
return response.data.map(function (item) {
return item;
});
});
};
}
};
i am using like this
<my-directivw url="api/user"> </my-directive>
Now instead of writing ng-model="user.selected" in template . i want to something like this
ng-model="somevar"
<my-directivw url="api/user" somevar="user.selected"> </my-directive>
How can i do that

It might help you.
The HTML code look like this.
<div ng-app="app" ng-controller="Ctrl as ctrl">
<form name="theform">
<range ng-model="ctrl.theRange" name="myRange" required="true"></range>
</form>
<button ng-click="ctrl.theRange = '10/100'">SET</button>
</div>
The JavaScript code look like this
var app = angular.module("app",[]);
app.controller("Ctrl", function($scope) {
this.theRange = "1/7";
});
app.directive("range", function() {
var ID=0;
function constructRangeString(from, to) {
var result;
if( !from && !to ) {
result = null;
}
else if( from ) {
result = from + "/" + (to || "");
}
else if( to ) {
result = "/" + to;
}
return result;
}
return {
require: "ngModel",
restrict: "E",
replace: true,
scope: {
name: "#"
},
template:
'<div ng-form="{{ subFormName }}">' +
'<input type="text" ng-model="from" class="range-from" />' +
'<input type="text" ng-model="to" class="range-to" />' +
'</div>',
link: function(scope,elem,attrs,ngModel) {
var re = /([0-9]+)\/([0-9]+)/;
if( scope.name ) {
scope.subFormName = scope.name;
}
else {
scope.subFormName = "_range" + ID;
ID++;
}
ngModel.$render = function() {
var result, from, to;
result = re.exec(ngModel.$viewValue);
if( result ) {
from = parseInt(result[1]);
to = parseInt(result[2]);
}
scope.from = from;
scope.to = to;
};
scope.$watch("from", function(newval) {
var result = constructRangeString(newval, scope.to);
ngModel.$setViewValue(result);
});
scope.$watch("to", function(newval) {
var result = constructRangeString(scope.from, newval);
ngModel.$setViewValue(result);
});
}
};
});

Related

AngularJS: I can't understand a custom directive

Can someone help me to understand this code? I've found this code in a project and I need a directive that allows only numeric input in text areas, can this help me?
controllerManager.directive('chars', function () {
'use strict';
return {
require: 'ngModel',
restrict: 'A',
link: function ($scope, $elem, attrs, ctrl) {
var regReplace,
preset = {
'specialChars': "^\x20-\x22\x27-\x3F\x41-\x59\x61-\x7B\x7D",
'integer': "0-9"
},
filter = preset[attrs.chars] || attrs.chars;
$elem.on('input', function () {
regReplace = new RegExp('[' + filter + ']', 'ig');
ctrl.$setViewValue($elem.val().replace(regReplace, ''));
ctrl.$render();
var max = $elem.attr('maxLength');
var len = $elem.val().length;
document.getElementById($elem.attr('id')+"Count").innerHTML = max - len;
});
}
};
});
Use below directive. It will only allow integer values to be entered and will discard any other character.
app.directive('integerOnly', ['$compile', function ($compile) {
return {
restrict: 'A',
require: "ngModel",
scope: {
ngModel: '='
},
link: function (scope, element, attrs, ngModelCtrl) {
var oldValue = null;
element.addClass('text-right');
element.bind('focus', function () {
return scope.$apply(function () {
return oldValue = element.val();
});
});
return ngModelCtrl.$parsers.unshift(function (inputValue) {
var val = inputValue ? inputValue.toString().replace(/[^0-9]/g, '') : "";
while (val < "1" && val != val.replace(/[^1-9]/, '')) {
val = val.replace(/[^1-9]/, '');
}
if (val !== inputValue) {
ngModelCtrl.$setViewValue(val);
ngModelCtrl.$render();
}
return val;
});
}
};
}]);
I resolved with this change:
controllerManager.directive('chars', function () {
'use strict';
return {
require: 'ngModel',
restrict: 'A',
link: function ($scope, $elem, attrs, ctrl) {
var regReplace,
preset = {
'specialChars': "^\x20-\x22\x27-\x3F\x41-\x59\x61-\x7B\x7D",
'integer': "^0-9"
},
filter = preset[attrs.chars] || attrs.chars;
$elem.on('input', function () {
regReplace = new RegExp('[' + filter + ']', 'ig');
ctrl.$setViewValue($elem.val().replace(regReplace, ''));
ctrl.$render();
var max = $elem.attr('maxLength');
var len = $elem.val().length;
document.getElementById($elem.attr('id')+"Count").innerHTML = max - len;
});
}
};
});
So now this work:
<input type="text" chars="integer"/>

Custom directive for Tagging using angularJS

I'm not able to add tag in my text field. Can anyone help me with an approach to add text in a text field as tagging. How to bing the tag to a json object or an variable.
</script>
<script>
var app = angular.module('myApp',[]);
app.directive('tagInputType', function() {
return {
restrict: 'E',
scope: { tags: '=' },
template:
'<div class="tags">' +
'<a ng-repeat="(idx, tag) in tags" class="tag" ng-click="remove(idx)">{{tag}}</a>' +
'</div>' +
'<input type="text" placeholder="Add a tag..." ng-model="new_value"></input> ' +
'<input type="button" value="Add" ng-click="add()"></input>',
link: function ( $scope, $element ) {
// var input = angular.element( $element.children()[1] );
$scope.add = function() {
$scope.tags.push( $scope.new_value );
$scope.new_value = "";
};
$scope.remove = function ( idx ) {
$scope.tags.splice( idx, 1 );
};
input.bind( 'keypress', function ( event ) {
if ( event.keyCode == 13 ) {
$scope.$apply( $scope.add );
}
});
}
};
});
app.controller('MainCtrl', function ( $scope ) {
$scope.tags = { "value1":"angular","value2":"html"};
});
</script>
<script>
App.directive('dhTag', function($compile) {
return {
restrict: 'AE',
scope: {
taglist: '=list',
autocomplete: '=autocomplete',
display: '='
},
link: function($scope, element, attrs) {
$scope.defaultWidth = 490;
$scope.tagText = "";
$scope.placeholder = attrs.placeholder;
$scope.display = attrs.display;
$scope.tagArray = function() {
return $scope.taglist || [];
};
$scope.addTag = function() {
//debugger
var tagArray;
if ($scope.tagText.length === 0) {
return;
}
tagArray = $scope.tagArray();
for (var i = 0; i < tagArray.length; i++) {
if (tagArray[i].name == $scope.tagText) {
alert("Tag already exists in the content box!!");
return;
}
}
tagArray.push({
name: $scope.tagText
});
$scope.taglist = tagArray;
$scope.tagText = "";
};
$scope.deleteTag = function(key) {
var tagArray;
tagArray = $scope.tagArray();
if (tagArray.length > 0 && $scope.tagText.length === 0 && key === undefined) {
tagArray.pop();
} else {
if (key !== undefined) {
tagArray.splice(key, 1);
}
}
$scope.taglist = tagArray;
};
$scope.$watch('tagText', function(newVal, oldVal) {
var temp;
if (!(newVal === oldVal && newVal === undefined) && temp) {
//temp = $("<span>" + newVal + "</span>").appendTo("body");
$scope.inputWidth = temp ? temp.width() : 0;
if ($scope.inputWidth < $scope.defaultWidth) {
$scope.inputWidth = $scope.defaultWidth;
}
return temp.remove();
}
});
$scope.processKey = function(e) {
var key;
key = e.which;
if (key === 9 || key === 13 || key === 188) {
$("div").find('.dh-tag-ctn .input-tag').css({
"background-color": " #FCF8E3"
});
e.preventDefault();
return $scope.addTag();
}
if (key === 8) {
$("div").find('.dh-tag-ctn .input-tag').css({
"background-color": "rgba(255, 0, 0, 0.15)"
});
$scope.deleteTag();
}
};
},
//templateUrl: "tagInputTemplate.html",
template: "" +
"<div class='dh-tag-ctn'>" +
" <div class='input-tag' ng-hide={{display}} data-ng-repeat=\"tag in tagArray() track by $index\" ng-class='tag' >" +
" <span>{{tag.name}}</span>" +
" <div class='delete-tag' data-ng-click='deleteTag($index)'> ×</div>" +
" </div>" +
" <input type='text' data-ng-style='{width: inputWidth}' ng-model='tagText' ng-keypress='processKey($event)' ng-keyup='processKey($event)' placeholder='{{placeholder}}' />" +
"</div>" +
"<br>" +
"<div ng-show={{display}} class='dh-tag-ctn-view'><div class='input-tag' data-ng-repeat=\"tag in tagArray() track by $index\" ng-class='tag'>{{tag.name}}" +
" <div class='delete-tag' data-ng-click='deleteTag($index)'>×<br></div>" +
"</div>"
};
});
</script>

how to append the specific values in array?

This is my directive.I want to append the array specific array value in existing array
localStorage.getItem('albumcomments') = "[{"id":1,"photocomment":"sdfsdfs"}]";
angular.module('albumlikeFeature',[]).directive('albumlikeFeature', ['$filter', '$route', function ($filter, $route) {
return {
restrict: 'E',
scope: {},
templateUrl: 'app/components/album/albumlikefeature.html',
link : function(scope, element, attrs) {
scope.likeCount = 0;
scope.unlikeCount = 0;
scope.likeClick = function (dataid) {
scope.likeCount += 1;
if(JSON.parse(localStorage.getItem('albumcomments'))){
var newDataLike = [];
angular.forEach(localStorage.getItem('albumcomments'), function(likeCount, item){
console.log('test');
newDataLike.push({id:item.id, photocomment:item.photocomment, like:likeCount});
});
console.log(newDataLike);
localStorage.setItem('albumcomments',JSON.stringify(newDataLike));
}
};
My expected output is
[{"id":1,"photocomment":"test","like":"1","unlike":"1"}
Now output is
[{"like":"["},{"like":"{"},{"like":"\""},{"like":"i"},{"like":"d"},{"like":"\""},{"like":":"},{"like":"1"},{"like":","},{"like":"\""},{"like":"p"},{"like":"h"},{"like":"o"},{"like":"t"},{"like":"o"},{"like":"c"},{"like":"o"},{"like":"m"},{"like":"m"},{"like":"e"},{"like":"n"},{"like":"t"},{"like":"\""},{"like":":"},{"like":"\""},{"like":"s"},{"like":"d"},{"like":"f"},{"like":"s"},{"like":"d"},{"like":"f"},{"like":"s"},{"like":"\""},{"like":"}"},{"like":"]"}]
Try this hope it will help
angular.module('albumlikeFeature',[]).directive('albumlikeFeature', ['$filter', '$route', function ($filter, $route) {
return {
restrict: 'E',
scope: {},
templateUrl: 'app/components/album/albumlikefeature.html',
link : function(scope, element, attrs) {
scope.likeCount = 0;
scope.unlikeCount = 0;
scope.likeClick = function (dataid) {
scope.likeCount += 1;
if(JSON.parse(localStorage.getItem('albumcomments'))){
var newDataLike = [];
angular.forEach(JSON.parse(localStorage.getItem('albumcomments')), function(likeCount, item){
newDataLike.push({id:likeCount.id, photocomment:likeCount.photocomment, like:scope.likeCount,unlike:scope.unlikeCount});
});
localStorage.setItem('albumcomments',JSON.stringify(newDataLike));
}
};
scope.unlikeClick = function (dataid) {
scope.unlikeCount += 1;
if(JSON.parse(localStorage.getItem('albumcomments'))){
var newDataUnlike = [];
angular.forEach(JSON.parse(localStorage.getItem('albumcomments')), function(i, item){
newDataUnlike.push({id:i.id, photocomment:i.photocomment,like:scope.likeCount,unlike:scope.unlikeCount});
});
console.log(newDataUnlike);
localStorage.setItem('albumcomments',JSON.stringify(newDataUnlike));
}
};
}
}
}]);
I guess you should create a new array and then you can push the things while iterating:
var data = [{"id":1,"photocomment":"test"},{"id":1,"photocomment":"test1"}];
var newData = [];
$.each(data, function(i, item){
newData.push({id:item.id, photocomment:item.photocomment, like:i, unlike:i});
});
console.log(newData);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
localStorage.getItem('albumcomments') = JSON.parse('[{"id":1,"photocomment":"sdfsdfs"}]');
angular.module('albumlikeFeature',[]).directive('albumlikeFeature', ['$filter', '$route', function ($filter, $route) {
return {
restrict: 'E',
scope: {},
templateUrl: 'app/components/album/albumlikefeature.html',
link : function(scope, element, attrs) {
scope.likeCount = 0;
scope.unlikeCount = 0;
scope.likeClick = function (dataid) {
scope.likeCount += 1;
if(localStorage.getItem('albumcomments').length > 0){
var newDataLike = [];
$.each(localStorage.getItem('albumcomments'), function(value, key){
$(this) = $this;
console.log('test');
newDataLike.push( {id: $this.id, photocomment: $this.photocomment, like: scope.likeCount} );
});
console.log(newDataLike);
localStorage.setItem('albumcomments',JSON.stringify(newDataLike));
}
};
Try that

Pass scope and parameters to directive - AngularJS

I'm trying to set a class in a ng-repeat with a directive.
I need to pass a parameter to this directive: wineQty
if I use scope: { wineQty: '=' } this works however $scope.bullet1Color is undefined in my html and thus doesn't affect the class that I want.
If I use scope: '#' I get the correct class however I can't specify wineQty
Is there a way to combine theses two syntaxes? so that I can access the scope and pass a paramater?
I've tried { wineQty: '#' } but with no luck sadly.
Here's my directive
angular.module('myApp').directive('wineQtyBullets', function () {
return {
restrict: 'A',
scope: { wineQty: '=', totalBullets: '=', numRedBullets: '=', numOrangeBullets: '#', bullet1Color: '#' },
link: function (scope, element, attrs) {
// defaults
var defaultNumRedBullets = 1;
var defaultNumOrangeBullets = 2;
var defaultTotalBullets = 12;
var defaultWineQty = 0;
// set values from attributes
var numRedBullets = scope.numRedBullets ? scope.numRedBullets : defaultNumRedBullets;
var numOrangeBullets = scope.numOrangeBullets ? scope.numOrangeBullets : defaultNumOrangeBullets;
var totalBullets = scope.totalBullets ? scope.totalBullets : defaultTotalBullets;
var wineQty = scope.wineQty ? scope.wineQty : defaultWineQty;
for (var currentBullet = 1; currentBullet <= totalBullets; currentBullet++) {
var bulletColorClass = 'bg-grey';
if (currentBullet <= wineQty) {
if (currentBullet <= numRedBullets) {
bulletColorClass = 'bg-red';
}
else if (currentBullet <= (numOrangeBullets + numRedBullets)) {
bulletColorClass = 'bg-orange';
}
else {
bulletColorClass = 'bg-green';
}
}
scope["bullet" + currentBullet + "Color"] = bulletColorClass;
}
console.log(scope.bullet1Color);
}
};
}
);
Here's my html
<div class="bullets pull-left ml15 mt6" wine-qty="wine.owned_qty" wine-qty-bullets>
<ul>
<li class="bullet"
ng-class="bullet1Color"></li>
</ul>
</div>
I managed to solve the problem, by changing scope to true and accessing the parameters through attrs
If this can help anyone here's the directive:
angular.module('myApp').directive('wineQtyBullets', function () {
return {
restrict: 'A',
scope: true,
link: function (scope, element, attrs) {
var options = { };
angular.forEach([
'numRedBullets',
'numOrangeBullets',
'totalBullets',
'wineQty'
], function (key) {
if (angular.isDefined(attrs[key]))
options[key] = attrs[key];
});
// defaults
var defaultNumRedBullets = 1;
var defaultNumOrangeBullets = 1;
var defaultTotalBullets = 12;
var defaultWineQty = 0;
// set values from attributes
var numRedBullets = parseInt(options.numRedBullets) ? parseInt(options.numRedBullets) : defaultNumRedBullets;
var numOrangeBullets = parseInt(options.numOrangeBullets) ? parseInt(options.numOrangeBullets) : defaultNumOrangeBullets;
var totalBullets = parseInt(options.totalBullets) ? parseInt(options.totalBullets) : defaultTotalBullets;
var wineQty = parseInt(options.wineQty) ? parseInt(options.wineQty) : defaultWineQty;
for (var currentBullet = 1; currentBullet <= totalBullets; currentBullet++) {
var bulletColorClass = 'bg-grey';
if (currentBullet <= wineQty) {
if (wineQty <= numRedBullets) {
bulletColorClass = 'bg-red';
}
else if (wineQty <= (numOrangeBullets + numRedBullets)) {
bulletColorClass = 'bg-orange';
}
else {
bulletColorClass = 'bg-green';
}
}
scope["bullet" + currentBullet + "Color"] = bulletColorClass;
}
}
};
});
Using "=" means 2-way data binding, and it's definitely fine.
The problem might be that your link function are executed only once at the very beginning, when it's possible that the values of your attributes are not yet assigned (may be caused by some AJAX calls).
I would suggest that you wrap all your link function into a scope.$watch function. Like:
link: function (scope, element, attrs) {
scope.$watch(function() {
return {
wineQty: scope.wineQty,
totalBullets: scope.totalBullets,
numRedBullets: scope.numRedBullets,
numOrangeBullets: scope.numOrangeBullets,
bullet1Color: scope.bullet1Color
}
}, function() {
// Your original code here.
})
}
Then your final result will automatically update if your directive got new attribute values.

How do I write an Angular directive to transform text to mark-up

I have this template
<span highlight>{{player.Name}}</span>
and this directive
wcApp.directive('highlight', function() {
return {
restrict : 'A',
link : function (scope, element, attrs) {
var nameStr = element.text();
nameStr = $.map(nameStr,function(letter){
return letter == ' ' ? ' ' : letter;
});
element.html('<span>' + nameStr.join('</span><span>') + '</span>');
}
};
});
But it's not working. I want to grab the text in the span, break-up the letters and wrap each character in a span.
What am I doing wrong?
The problem is the binding, element haven't been compiled yet, there is diffrent way to solve this (prioritize you directive after compile, binding & compiling it yourself with the compileProvider)
wcApp.directive('highlight', function() {
return {
restrict : 'A',
link : function (scope, element, attrs) {
var nameStr = element.text();
alert(nameStr); // {{player.Name}}
nameStr = $.map(nameStr,function(letter){
return letter == ' ' ? ' ' : letter;
});
element.html('<span>' + nameStr.join('</span><span>') + '</span>');
}
};
});
Alternative solution:
<span highlight="player.name"></span>
...and js
wcApp.directive('highlight', function() {
return {
restrict : 'A',
scope: {highlight: "="},
link : function (scope, element, attrs) {
var nameStr = scope.highlight;
// alert(nameStr); // not {{player.Name}}
nameStr = $.map(nameStr,function(letter){
return letter == ' ' ? ' ' : letter;
});
element.html('<span>' + nameStr.join('</span><span>') + '</span>');
}
};
});
simpulton have written a very good blog post about this worth reading:
http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/
try
.directive('highlight', function() {
return {
restrict : 'A',
template: '<span ng-repeat="l in letters">{{ l.letter }}</span>',
link : function (scope, element, attrs) {
var nameStr = attrs.highlight;
nameStr = nameStr.split("");
var map = [];
var i=0, len=nameStr.length;
for (; i<len; i++) {
map.push({letter: nameStr[i] = nameStr[i].replace(" ", " ")});
}
scope.letters = map;
}
};
});

Categories

Resources