Angular pass dynamic scope to directive - javascript

I have a directive that takes an attribute value from a an http call like so:
Controller
app.controller("HomeController", function($scope){
$http.get("/api/source").then(function(res){
$scope.info = res.data
});
});
HTML
<div ng-controller="MainController">
<ng-mydirective data-info="{{info}}"></ng-mydirective>
</div>
Directive:
app.directive("ngMydirective", function(){
return {
restrict: "E",
templateUrl: "/partials/info.html",
link: function(scope, element, attrs){
scope.info = attrs.info;
}
}
});
I'm trying to pass that info variable from the controller, into the directive, through an attribute. It doesn't work because the variable value is initially created from an asynchronous http call, so at the time the directive is created, there is no value.
Is there a way to do this?

You can observe the attribute's value:
link: function(scope, element, attrs){
attrs.$observe('info', function(val) {
scope.info = val;
})
}
Also, if you can change the directive scope to be isolated, you can do it by binding the values:
app.directive("ngMydirective", function(){
return {
restrict: "E",
scope: {info: '='},
templateUrl: "/partials/info.html",
link: function(scope, element, attrs){
}
}
});
<div ng-controller="MainController">
<ng-mydirective info="info"></ng-mydirective>
</div>

Related

AngularJs directives - Need to get attribute value in templateUrl

I need to get append directive attribute value to templateUrl.
I tried several options however, templateUrl does not support $observe in it.
Therefore I tried below and tried to get "devicePath" value to templateUrl.
Nothing worked.
Here is my example.
<me-direct device-path="{{contentUrl}}" tmp-url="{{appTemplateUrl}}"></me-direct>
Directive js file
angular.module('meDevices').directive('medirect',medirect);
function medirect(){
return{
scope:{
devicePath:'#'
},
restrict: 'E',
controller: 'directCtrl',
link: function(scope, element, attrs) {
// some ode
attrs.$observe('devicePath', function(value){
console.log(value);
scope.url = value;
console.log(scope.url);
});
},
templateUrl: scope.url
}
}
Anyhow, this is not working since scope.url is not accessible from templateUrl. Any thoughts??
EDIT
But If I send attribute as this everything will work.
<me-direct device-path="some/common/url/to/view.html" tmp-url="{{appTemplateUrl}}"></me-direct>
Try this:::
angular.module('meDevices').directive('medirect',medirect);
function medirect(){
return{
restrict: 'E',
scope: {
base: '#baseUrl'
},
templateUrl: function(element, attrs) {
return "http://example.com/"+attrs['device-path']+attrs['tmp-url'];
}
}
}
Uses:
<me-direct device-path="{{contentUrl}}" tmp-url="{{appTemplateUrl}}"></me-direct>

Not able to get custom directive attribute value

I've a custom directive called "mycomponent".
restrict: 'AE',
templateUrl: 'template.html',
scope:{
sTransactionType: '=transactionType',
sStorageVariable: '=storageVariable'
},
link: function(scope, element, attrs){
console.log("attrs.transactionType:: "+attrs.transactionType);
console.log("scope.sTransactionType:: "+scope.sTransactionType);
And markup as:
<my-component transaction-Type="FundTransfer" storage-Variable="FundTransferToday"></my-component>
Now, when I try to access the value of attributes transaction-Type and storage-Variable in link function of directive, it returns undefined.
Values can be accessed by attrs.transactionType but not able to get it with scope.sTransactionType.
I tried to change attribute name, scope varibale name.
How do I get custom directive attribute values in scope variables ?
Updated code:
var fundtransfer = angular.module("fundtransfer",['mydirectives']);
var controllers = {};
controllers.cntFundTransfer = function($scope, $rootScope){
}
var mydirectives = angular.module("mydirectives",['Constants']);
mydirectives.directive('myComponent', function($rootScope){
restrict: 'AE',
templateUrl: 'template.html',
scope:{
sTransactionType: '=transactionType',
sStorageVariable: '=storageVariable'
},
link: function(scope, element, attrs){
console.log("scope.sTransactionType:: "+scope.sTransactionType);
}
}
<my-component transaction-type="FundTransfer" storage-variable="FundTransferToday"></my-component>
Your attribute naming is wrong.
all should be in lowercase
try like this
<my-component transaction-type="FundTransfer" storage-variable="FundTransferToday"></my-component>
JS
restrict: 'AE',
templateUrl: 'template.html',
scope:{
sTransactionType: '=transactionType',
sStorageVariable: '=storageVariable'
},
link: function(scope, element, attrs){
console.log("scope.sTransactionType:: "+scope.sTransactionType);
}

Update $watch using require in angular directive

as an angular newbie this is my problem
If I have two directives in HTML like this
<parent-dir param="par">
<child-dir></child-dir>
</parent-dir>
and in JS like this (in parent)
app.directive('parentDir', function(){
return {
restrict: 'E',
scope: {
param: '='
}
}
})
and in child
app.directive('childDir', function(){
return {
restrict: 'E',
require: '^parentDir',
controller: function($scope, $element){
<-- SHOULD I PUT WATCHER HERE -->
},
link: function(scope, element, attrs, parentdirCtrl){
<-- SHOULD I PUT WATCHER HERE -->
}
}
})
where in the child directive should I make an optional $watch in order to catch all changes to the param model?
Off course if I use $watch in the parent controller, all changes in the param are reflected in the parent directive but I can`t seem to find a way to pass this information to child directive.
You should place it inside the link function which have access of the parent controller using 4th parameter of link function parentdirCtrl. Actually you don't need to worry about the params variable because it uses = two way binding inside directive that does update the value in both parent controller scope & directive scope. Additionally you need define controller in your parentDir directive so that the scope of parentDir directive shared with the childDir.
Code
app.directive('childDir', function() {
return {
restrict: 'E',
require: '^parentDir',
template: '<div class="test">INner {{param}}</div>',
controller: function($scope, $element) {
},
link: function(scope, element, attrs, parentdirCtrl) {
scope.$watch('param', function(newVal, oldVal) {
console.log(newVal);
}) //true only if its object.
}
}
})
Demo Plunkr

Angular directive not applied on change of the value

I have a directive like
testApp.directive('changeValue', function(){
alert("coming");
return {
restrict: 'E',
link: function (scope, element, attrs) {
element.text(attrs.val);
},
replace: true
};
});
and I have my views as follows
<change-value val="{{test.val}}"/>
When I refresh my page, I could see the values and I get the alerts. But when the value is changed I don't get it applied to the directive but it binds to the view as I could see it being changed outside when simply called like
<span>{{test.val}}</span>
I am not sure how this works. Thanks in Advance!
In your code, the link function is executed only once so the value is updated only when the directive instance is created. Since you want to have a watch of its value and keep updating the text you can use $observe()
var app = angular.module('my-app', [], function() {})
app.controller('AppController', function($scope) {
$scope.test = {
val: "Welcome"
};
});
app.directive('changeValue', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
attrs.$observe('val', function() {
element.text(attrs.val);
})
},
replace: true
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="my-app" ng-controller="AppController">
<change-value val="{{test.val}}"></change-value>
<input ng-model="test.val" />
</div>

How to apply a directive after a transclusion in AngularJS

I'm trying to access a transcluded element in an element directive from a different inner directive applied within the first directive's template.
My (trivial example) setup:
Element directive
.directive('elementDirective', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'template.html',
link: function (scope, elem, attr, ctrl, transclude) {
elem.find('transclusion').replaceWith(transclude());
}
};
})
Template
<div inner-directive>
<div id="transclusion"></div>
</div>
Inner Directive
.directive('innerDirective', function() {
return {
restrict: 'A',
link: function (scope, elem, attr, ctrl) {
//Do something here with child elements (which will be transcluded).
var some = elem[0].querySelector('[name]');
//...
}
};
})
Html
<element-directive>
<input name="input_name" />
</element-directive>
My Error:
I get an error of the kind.
element-directive element has no child input elements with a 'name' attribute
I'm assuming this means that the inner directive is compiled, linked, whatnot, before transclusion happens. So, how can I achieve what I'm trying to do?

Categories