AngularJS directive pass parameters through templateUrl function - javascript

I'm trying to move my template from being in-line to it's own file. Everything was working before I changed from template to templateUrl
Glenn.directive('test', function($compile) {
return {
restrict: 'A',
priority: 1000,
terminal: true,
templateUrl: function(tElement, tAttrs) {
return ('test.html');
},
link: function(scope, element, attrs) {
attrs.$set('editable-text', 'content.' + attrs.edit + '.data');
attrs.$set('edit', null);
$compile(element)(scope);
}
}
});
test.html
{{ 'content.' + tAttrs.edit + '.data' }}
<button ng-click="' + tAttrs.edit + '_form'+ '.$show()" ng-hide="' + tAttrs.edit + '_form'+ '.$visible">edit</button>
Why isn't the tAttrs being passed to my template test.html?

I never seen this that way, i always pass an string to the templateUrl property like
...
templateUrl: './foodirective.tmpl.html'
...
You could assign the attrs from your directive element in the linking function:
myApp.directive('fooDirective', function(){
return{
restrict: 'E',
scope: true,
templateUrl: './foodirective.tmpl.html',
link: function(scope, elem, attrs){
// do stuff
scope.tAttrs = attrs;
}
}
})
I've prepared a plunk for you.

Related

how to use angular expression value as an attribute for html element

I have a scenario where i need to apply different directives (attribute) to a DIV inside a Angular bootstrap Modal at runtime (button click).
I would know the name of the directive to apply. But i am not able to figure out how to change the template at runtime to add necessary directive name as an attribute to the DIV.
consider this plunker
Basically i want the div to have child directive as an attribute using synstax like this
<div {{child}}></div>
So when it works, it should generate <div child-directive></div>
How can this be done? is this even possible? What is the best way to change the template before opening the Modal so that it wires up correctly when loaded.
// Code goes here
var app = angular.module('main-module', ['ui.bootstrap']);
app.directive('parentDirective', function($uibModal, $compile) {
return {
restrict: 'E',
template: "<h2>I am Parent</h2><button ng-click='click()'>Click Me</button>",
scope: {
child:'#'
},
link: function($scope, elem, attrs) {
console.log('?',$scope.child, $scope);
var template = "<div><h3>This is modal</h3>"
+ "Ideally you should see the child directive below"
+ "<hr />"
+ "<div "+ $scope.child + "></div></div>";
$scope.click = function() {
$uibModal.open({
template: template,
scope: $scope,
size: 'lg',
});
}
}
};
})
.directive('childDirective', function() {
return {
restrict: 'A',
template: "<div><h4>I am Child</h4><a ng-click='click()'>Click Me!!</a></div>",
replace: true,
scope: {},
link: function($scope, elem, attrs) {
$scope.click = function() {
alert("I am in child scope");
}
}
};
}).directive('anotherChildDirective', function() {
return {
restrict: 'A',
template: "<div><h4>I am another Child</h4><a ng-click='click()'>Click Me!!</a></div>",
replace: true,
scope: {},
link: function($scope, elem, attrs) {
$scope.click = function() {
alert("I am in child scope");
}
}
};
});;

AngularJS - follow scope in custom directive

I have custom directive and want to send some parameters(objects) to this directive.
In directive I have select list based on one of this parameters and I need to follow this parameter.
My directive:
<custom-directive rows="users">
</custom-directive>
and template:
<ui-select ng-model="value">
<ui-select-match allow-clear="true">
{{$select.selected}}
</ui-select-match>
<ui-select-choices repeat="row in rows | filter: $select.search">
<div>
<span ng-bind-html="row | highlight: $select.search"></span>
</div>
</ui-select-choices>
</ui-select>
normally if rows change ui-select will automatically update select list. But if rows is variable from outside of this directive, it wont.
Can I have the same variable outside and inside directive?
I think I can use ng-model, but I'm not sure it is good solution.
EDIT:
My directive code:
.directive('custom-directive', function () {
return {
restrict: 'E',
replace: true,
scope: {
rows: '='
},
templateUrl: 'template.html',
controller: ['$scope', function($scope) {
console.log($scope);
}]
};
})
You can modify your custom directive to work with ng-model in the following way:
directive('customDirective', function() {
return {
// ...
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if (!ngModel) return;
// Write data to the model
// Call it when necessary
scope.setValue = function(value) {
ngModel.$setViewValue(value);
}
}
};
});
Initial state of ng-model value can be retrieved using that method:
ngModel.$render = function() {
var value = ngModel.$viewValue || [];
};
You can use link instead of the controller to handle functionality with rows. Setting rows : '=' should already take care of the two-way binding.
.directive('custom-directive', function () {
return {
restrict: 'E',
replace: true,
scope: {
rows: '='
},
templateUrl: 'template.html',
link: function(scope, element, attr) {
console.log(scope.rows);
};
};
})
EDIT:
Add a watch to the value that you need to do behavior on external change.
.directive('custom-directive', function () {
return {
restrict: 'E',
replace: true,
scope: {
rows: '='
},
templateUrl: 'template.html',
link: function(scope, element, attr) {
scope.$watch('rows', function(oldValue, newValue) {
console.log('This is the newValue : ' + newValue);
};
};
};
})

How to make two way binding between angular directives without using "dots"

Suppose, I have controller:
angular.module('tf').controller('Ctrl', function($scope){
$scope.params = {
orderBy: null
};});
And a directive "common":
angular.module('tf').directive("common", function() {
return {
restrict: 'E',
replace: true,
template: '<div><outer order-by="orderBy"><inner order-by-field="name1"></inner><inner order-by-field="name2"></inner></outer></div>',
controller: function ($scope) {
},
scope: {
orderBy: '='
},
link: function (scope, element, attrs) {
}
}});
Controller is using directive within it's template:
<div ng-app="tf">
<div ng-controller="Ctrl">
<common order-by="params.orderBy"></common>
<div style="color:red">{{params.orderBy}}</div>
</div>
This directive is using directive "outer":
angular.module('tf').directive("outer", function() {
return {
restrict: 'E',
transclude: true,
replace: true,
template: '<div ng-transclude></div>',
controller: function ($scope) {
this.order = function (by) {
$scope.orderBy = by
};
},
scope: {
orderBy: '=',
}
}});
Which is parent for the directive "inner":
angular.module('tf').directive("inner", function() {
return {
require: '^outer',
restrict: 'E',
transclude: true,
replace: true,
template: '<div ng-click="onClicked()">{{orderByField}}</div>',
controller: function ($scope) {
$scope.onClicked = function () {
$scope.outer.order($scope.orderByField);
}
},
scope: {
orderByField: '#'
},
link: function (scope, element, attrs, outer) {
scope.outer = outer;
}
}});
The directive "outer" shares "order" method with directive "inner" by it's controller. The directive "inner" is accessing it by using "require" mechanism.
For some reason, this is not working as expected (Property of the controller isn't updated each time it's changed by directive). If I place "orderBy" into object (e.g. {"order": {"by": null }} ) and use object instead of string value, everything is working as expected ( controller scope is properly updated by the directive). I know about "always use dots" best practices principle, but I don't wanna use it here, because it would make my directive's API less intuitive.
Here is jsfiddle:
http://jsfiddle.net/A8Vgk/1254/
Thanks

Adding Multiple 'require' Options for Angular Directive

Usually in Directives, I use require: 'ngModel' if I want to pass the scope to it. This works fine. But I am now creating a directive that creates 5 different HTML elements each with different ngModels that is passed from parent. The ngmodels that needs to be passed as attribute are ngModel1, ngModel2, ngModel3, ngModel4, ngModel5. How do I add multiple options in the require condition inside the directive?
I tried these and it doesnt work:
require: ['ngModel1', 'ngModel2', 'ngModel3', 'ngModel4', 'ngModel5'],
and
require: {'ngModel1', 'ngModel2', 'ngModel3', 'ngModel4', 'ngModel5'},
and
require: 'ngModel1', 'ngModel2', 'ngModel3', 'ngModel4', 'ngModel5',
and
require: 'ngModel1, ngModel2, ngModel3, ngModel4, ngModel5'},
How do I add multiple require options?
EDIT:
HTML code:
<div get-vehicles-checkbox
cars-ng-model="formData.cars"
bikes-ng-model="formData.bikes"
trucks-ng-model="formData.trucks"
van-ng-model="formData.van"
bus-ng-model="formData.bus"
></div>
Directive:
app.directive('getVehiclesCheckbox', function($compile) {
return {
restrict: 'A',
replace:true,
// require: ?
scope: {
carsNgModel: '=',
bikesNgModel: '=',
trucksNgModel: '=',
vanNgModel: '=',
busNgModel: '='
},
controller: 'SomeController',
link: function(scope, element, attrs, carsNgModel, bikesNgModel, trucksNgModel, vanNgModel, busNgModel) {
scope.carsNgModel = {},
scope.bikesNgModel = {},
scope.trucksNgModel = {},
scope.vanNgModel = {},
scope.busNgModel = {}
var html = '<span ng-repeat="car in cars">' +
'<input type="checkbox" ng-model="carsNgModel[car.code]"> {{ car.number }} {{ car.description }}' +
'</span>' +
'<span ng-repeat="bike in bikes">' +
'<input type="checkbox" ng-model="bikesNgModel[bike.code]"> {{ bike.number }} {{ bike.description }}' +
'</span>';
//.... etc.. etc.....
// COMPILE HTML
//... .... ...
}
}
});
app.directive('myDirective', function() {
return {
restrict: "A",
require:['^parentDirective', '^ngModel'],
link: function ($scope, $element, $attrs, controllersArr) {
// parentDirective controller
controllersArr[0].someMethodCall();
// ngModel controller
controllersArr[1].$setViewValue();
}
}
});

AngularJS : Interpolating attributes

Say I have the following two directives:
angular.module('foo').directive('outer', [function(){
return {
restrict: 'E',
scope: {
inner: '#',
innneParams: '#'
},
template: "<div {{inner}}{{innerParams}}></div>",
link: function(scope, elem, attrs){
console.debug("I AM IN YOUR OUTER DIRECTIVE PASSING YOUR D00DZ!")
}
}
}]);
angular.module('foo').directive('innerDir', [function(){
return {
restrict: 'EA',
scope: {
innerParam: '='
},
template: "<div>{{massagedInner}}</div>",
link: function(scope, elem, attrs){
console.debug('I AM IN YOUR INNER DIRECTIVE MASSAGING YOUR D00DS!')
scope.massagedInner = scope.innerParam + "FROM YOUR DOGE!"
}
}
}]);
And the following HTML:
<outer inner="inner-dir" my-awesome-scope-value="myAwesomeScopeValue" inner-params="inner-param='myAwesomeScopeValue'"></outer>
The outer directive console debug triggers, the inner one does not. Is there a good way for me to achieve this kind of behaviour?
Plunk: http://plnkr.co/edit/jXbtWvYvtFXCTWiIZUDW?p=preview
There are quite a few things you're doing wrong. I've made the changes that I thought are close to what you wanted it to do and you can change the code from here.
Here's a working version
And this is what script.js now looks like;
angular.module('foo', []);
angular.module('foo').controller('fooController', ['$scope', function(scope){
scope.myAwesomeScopeValue = 'O HAI THERE'
}]);
angular.module('foo').directive('outer', [function(){
return {
restrict: 'E',
scope: {
// inner: '#',
// innnerParams: '#'
innerParam: '#'
},
template: "<div inner {{inner}} {{inner-param}}></div>",
link: function (scope) {
console.log('OUTER', scope.innerParam);
}
}
}]);
angular.module('foo').directive('inner', [function(){
return {
restrict: 'A',
// scope: {
// innerParam: '='
// },
replace: false,
template: "<div>{{massagedInner}}</div>",
link: function(scope, elem, attrs){
scope.massagedInner = scope.innerParam + "FROM YOUR DOGE!"
console.log('INNER');
}
}
}]);
For brevity, I've left some of your lines commented out. I hope this helps.

Categories