AngularJS: nested directives & Two-Way Binding - angularjs

I've created a directive pgPaginator:
function PaginatorDirective() {
return {
restrict: 'E',
require: 'ngModel',
templateUrl: 'paginator.html',
scope: {
ngModel: '=',
},
};
}
// ...
.directive('pgPaginator', PaginatorDirective)
paginator.html:
<input pg-paginator-page />
<select pg-paginator-perpage ng-model="ngModel.perpage" ng-options="option for option in ngModel.perpageOptions"></select>
<br />
{{ngModel}}
<br />
{{ngModel.page}}
and i tryed to create another directive pg-paginator-page that use pgPaginator scope:
.directive('pgPaginatorPage', function() {
return {
restrict: 'A',
replace: true,
template: '<input ng-model="ngModel.page" type="number" />',
link: function(scope, element, attrs) {
console.log(scope)
},
}
})
But when I create this directive, two-way binding is broken: http://embed.plnkr.co/h85hAk/preview
What am I doing wrong?

Related

How to get value from ng-model in directive?

I have code:
<input check-value-type-array type-value="node.type_value" type-element="node.type" ng-value="item" class="form-control">
And directive:
.directive('checkValueTypeArray', function() {
return {
restrict: 'A',
require: 'ngModel',
scope: {
typeElement: '=',
typeValue: '=',
ngModel: '='
},
link: function(scope, element, attrs, ngModel) {
ngModel.$validators.required = function(v) {}
}
How to get ng-model inside directive and do validation:
ngModel.$validators.required = function (v) {
}
Minor alteration, you're looking for ngModel.$modelValue:
ngModel.$validators.required = (value) => {
// the value of the model will be ngModel.$modelValue
}

Function inside directive not being triggered

Why my function toggleCategory function is not being triggered?
Directive
app.directive('asideFilter', function() {
return {
restrict: 'E',
scope: {
toggleCategory: '=&onToggleCategory'
},
transclude: true,
templateUrl: 'assets/directives/asideFilter/asideFilter.html',
link: function(scope, element, attrs){
}
};
});;
Directive template
<div ng-click="toggleCategory({id: 'teste'})">TEST</div>
Parent scope
$scope.onToggleCategory = function () {
console.log('onToggleCategory');
}
Parent Caller
<aside-filter toggle-category="onToggleCategory({id: 'test '})" categories="categories" />
You can call the parent controller function like this also
app.directive('asideFilter', function() {
return {
restrict: 'E',
scope: {
toggleCategory: '&',
},
transclude: true,
templateUrl: 'assets/directives/asideFilter/asideFilter.html',
link: function(scope, element, attrs){
scope.toggleCategoryClick = function (value) {
scope.toggleCategory(value);
}
}
};
});
Directive template
<div ng-click="toggleCategoryClick({id: 'teste'})">TEST</div>
Directive Element
<aside-filter toggle-category="onToggleCategory({id: 'test '})" categories="categories" />

Angular toggle directive from parent controller

How i can show/hide directive when some elements in parent controller has event?
app.directive('rest', function(){
return {
restrict: 'E',
scope: false,
replace: true,
link: function(scope, elem, attr) {
},
templateUrl: '<div ng-show="showDirective"></div>',
}
});
<div ng-controller="AppCtrl">
<rest></rest>
<div ng-click="showDirective = false"><div> <!-- hide directive -->
<div ng-click="showDirective = true"><div> <!-- show directive -->
</div>
Here, your mistake was "templateUrl" instead of "template". When you provide html inline, user "template", when you provide html in a separate html file, use "templateUrl" and provide a url to the template html:
http://plnkr.co/edit/xzqOvcjKYfWxazWfHWyS?p=preview
.directive('rest', function(){
return {
restrict: 'E',
scope: false,
replace: true,
link: function(scope, elem, attr) {
},
template: '<div ng-if = "showDirective" >Test</div>',
}

Attribute directive to work on an element inside another directive

I have hit a wall with what I need from angular, hopefully there's an easy way to achieve what I'm after.
I have a directive that looks something like that:
m.directive("string", function() {
return {
replace: true,
restrict: 'E'
scope: {'value':'='}
template: '<div>yada yada yada <input type="text" ng-model="value"/></div>'
};
});
I have another directive which must go on top of text input elements only:
m.directive("maskedString", function() {
restrict: 'A',
link: function(scope, element, attrs) {
// ... do stuff on the element
}
});
So... I can do that with no problem:
<input type="text" masked-string />
However, what I really need is:
<string masked-string />
This should end up setting the masked-string attribute on the input field before the template is compiled.
What is the best way to achieve that? 10x
I suggest you use compile method of the directive for this. Here is a working fiddle - http://jsfiddle.net/R4a62/1/
myApp.directive("string", function () {
return {
replace: true,
restrict: 'E',
scope: {
'value': '='
},
compile:function(element, attrs){
var newElement = angular.element('<div>yada yada yada <input type="text" masked-string ng-model="value"/></div>');
element.replaceWith(newElement);
}
};
});
You can do this with $compile. You only need to change the top-level directive. Here's a fiddle with an example. http://jsfiddle.net/D94t7/6/
m.directive("string", function ($compile) {
return {
replace: true,
restrict: 'E',
scope: {
'value': '=',
'drtv': '='
},
link: function(scope, element, attrs) {
var template = '<div>yada yada yada <input type="text" ng-model="value" '+ attrs.drtv +'/></div>';
// Add the HTML
var el = angular.element(template);
element.append(el);
// Compile and bind to scope
var compiled = $compile(el);
compiled(scope);
}
};
});

AngularJS - Share ngModel with nested directives and transcluded directives

I am trying to create 3 directives:
.directive('dirOne', function () {
return {
restrict: 'E',
transclude: true,
replace: true,
controller: function ($scope, $element, $attrs) {
this.add = function (tag) {
tag && $scope.tags.push(tag);
};
},
template: '<div><p>Bucket from directive: {{tags}}</p><div ng-transclude></div></div>'
};
})
.directive('dirTwo', function () {
return {
restrict: 'A',
replace: true,
require: '^dirOne',
link: function (scope, element, attrs, dirOne) {
scope.add = function (tag) {
dirOne.add(tag);
};
},
template: '<div>'+
' <input type="text" ng-model="query" datum="sugestions" dir-three>' +
' <button ng-click="add(query)">add</button>' +
'</div>'
};
})
.directive('dirThree', ['$compile', function ($compile) {
var itemsTemplate = '<span class="sugestions"><span ng-repeat="item in datum|filter:query">{{item.name||item}}</span></span>';
return {
restrict: 'A',
transclude: true,
replace: true,
require: 'ngModel',
scope: {
datum: '=',
query: '=ngModel'
},
link: function (scope, element, attrs) {
var parent;
element.wrap('<span>');
parent = element.parent();
parent.append(angular.element($compile(itemsTemplate)(scope)));
}
};
}])
In the dirTwo and dirThree, I have an input <input type="text" ng-model="query" datum="sugestions" dir-three> with ngModel, this input needs to access and modify the content of ngModel, so that the scope is not isolated.
http://jsfiddle.net/joaoneto/hbABU/3/
Update
I Updated version, fix some mistakes I had committed, the content that was being transcluded in dirTwo, should not have the "ADD" function, and belongs to dirTree, hope it helps someone and apologize for peopl take to update this entry... see in http://jsfiddle.net/hbABU/4/

Resources