AngularJS: ng-click of directive's child element not working - angularjs

I have set up the plunker to demonstrate the issue. The click of Bob button doesn't works. What I expected was, the child elements of the directive element will have the same isolated scope. Do I have to move the child elements into the template property of the directive?

I would define some object pass. Set up pass with method setDirectiveTitle and title:
Demo Plunker
JS
angular.module("myApp", [])
.directive("myScopedDirective", function() {
return {
scope: {
pass: '=',
preffix: "#msdTitle"
},
link: function($scope, $element, $attributes) {
$scope.pass.setDirectiveTitle = function(title) {
$scope.pass.title = $scope.preffix + title;
}
}
};
})
.controller("AppController", ["$scope", function($scope) {
$scope.passVal = {};
$scope.setAppTitle = function(title) {
$scope.passVal.title = title;
};
}]);
HTML
<div ng-controller="AppController">
<h2>{{title}}</h2>
<button ng-click="setAppTitle('App 2.0')">Upgrade Me!</button>
<div my-scoped-directive pass="passVal" msd-title="I'm a directive inside the app: {{passVal.title}}">
<h2>{{passVal.title}}</h2>
<button ng-click="passVal.setDirectiveTitle('Bob')" >Bob It!</button>
</div>
</div>

Problem is that is not compiled, you have to use transclusion in order to compile html inside a directive.
http://plnkr.co/edit/hGKeTqqU62Na0MWPvBIZ?p=preview
Or you can simply pass an template:
http://plnkr.co/edit/ZYhTdlwSDp0L3jjErOQt?p=preview
But you cannot use scope attribute binding in this case. Because on second update of parent scope , third click on child will not be updated as you expected.
You have to propagate data differently.

Related

Angular : Parent scope function not getting fired from directive button click

I'm trying to call the parent scope's function from the directive. But it's not getting fired. Can any one point out what is it that I'm missing ?
Here is my directive code:
.directive('myComp',function(){
return {
restrict:'E',
scope:{
vname:'&'
}
}
});
Here is the view code:
<my-comp vname="updateVal(val)">
<input type="text" ng-model="nm">
<button ng-click="vname({val:nm})">Save</button>
</my-comp>
And here is the controller code with the function:
.controller('View1Ctrl', ['$scope',function($scope) {
$scope.iname = 'roy';
$scope.updateVal = function(val){
alert('hi');
$scope.iname = val;
}
}])
It works fine if it is written under controller.
<div ng-app="app" ng-controller='View1Ctrl'>
<my-comp vname="updateVal(val)">
.....

Access parent as well as self controller in Angularjs directive

I have following fiddle where I am using require property of angular directive for accessing parent controller. Now I want to access both parent and self controller in link function of component directive.
<div ng-controller="MyCtrl">
<div screen>
<div component>
</div>
</div>
</div>
Is it possible to access self as well as parent directive controller in postlink function of directive
Have found the solution. I just need to mention same directive name in array of require property of directive definition object. FIDDLE
.directive('component', function() {
return {
scope: true,
require: ['component','^screen'],
controller: function($scope) {
this.componentFunction = function() {
$scope.screenCtrl.doSomethingScreeny();
}
},
link: function(scope, element, attrs, screenCtrl ) {
scope.screenCtrl = screenCtrl
console.log(screenCtrl);
}
}
})

After $compile controller of new element works but data binding not

I add DOM element (externally to Angular), $compile it and link it with scope in directive's event handler - controller defined in ng-controller of new element fires up, but databinding is not working - the result is
{{data.name}}
like it's not compiled at all ... Why?
(I use $compile for the first time so, maybe I'm missing something)
Below is just directive's code:
app.directive('pages', function ($compile) {
return {
restrict: 'E',
link: function (scope, element) {
element.on('pageLoaded', function(event){
var page = angular.element(event.detail.element);
var linkFn = $compile(page);
scope.data = {
name: 'DATA SET IN DIRECTIVE'
};
linkFn(scope);
});
}
}
});
Page I add (dom element in event.detail.element) is
<div page="AddedPage" ng-controller="PageController">
{{data.name}}
</div>
Here is jsfiddle: http://jsfiddle.net/yoorek/EYCwY/
You didn't add the element to the DOM. See this Fiddle:
scope.$apply(function () {
element.replaceWith($compile(page)(scope));
});
If you want to add multiple pages, append it instead of replacing it.
Furthermore, I recommend reading through this post on the recommendations and concepts of AngularJS.
Add addPage into controller and use ng-click
http://jsfiddle.net/EYCwY/1/
<div ng-app="app" ng-controller="AppController">
<button ng-click="addPage()">Add Page</button>
<pages>
<page page="StaticPage">
</page>
</pages>
app.controller('AppController', function ($scope) {
log('App Controller');
$scope.data = {
name: 'Data set in AppController'
}
$scope.addPage = function () {
var page = document.createElement('div');
var parent = document.getElementsByTagName('pages')[0];
page.setAttribute('page', 'AddedPage');
page.setAttribute('ng-controller', 'PageController');
page.innerHTML = '{{data.name}}';
parent.appendChild(page);
var event = new CustomEvent(
"pageLoaded",
{
detail: {
page: "AddedPage",
element: page
},
bubbles: true,
cancelable: true
}
);
parent.dispatchEvent(event);
};
});

Directive - controller data binding in AngularJS

I'm struggling with this for hours now.
var testApp = angular.module('testApp', []);
testApp.directive('test', function() {
return {
restrict: 'E',
transclude: true,
template: '<div ng-transclude>Hello World</div>',
link: function(scope) {
}
}
});
testApp.controller('testCtrl', function ($scope) {
$scope.user = "";
});
Here's JSFiddle: http://jsfiddle.net/2bKPj/
Now, all I need is for an input embedded in directive to be able to reflect user model directly in testCtrl controller.
I'm confused on how this beast works since I taught that scopes are shared in this case, no?
ngTransclude creates a new child scope which protorypically inherits from it's parent scope.
When you use a primitive on the child scope it shadows the parent scope's variable.
It's been already said thousand times: use the dot notation!
controller:
testApp.controller('testCtrl', function ($scope) {
$scope.data = { user : "Hello World" };
});
html:
<input type="text" ng-model="data.user"/><br />
Directive model:<span>{{ data.user }}</span>
Check my other answers for description:
bound element inside ngIf does not update binding
Directives inside ng-include

Angularjs Two way binding issues

I'm trying to create a dynamic directive that will receive his binding options from attributes.
This is my controller view:
<div ng-controller="OtCtrl">
<div ng-include src="'/client/views/openTradeView.html'"></div>
</div>
my View:
<div>
{{name}}
<div swings binding="Risk" title="Risk"></div>
<div swings binding="Amount" title="Amount"></div>
</div>
This is my directive View:
<div>
{{title}}
-
{{amount}}
+
</div>
This is my directive:
app.directive("swings", function () {
return {
replace: true,
scope: {
title : '#title',
amount: '=binding',
extra: '=bindingExtra'
},
resctrict: "A",
controller: function($scope){
$scope.minus = function (event, binding) {
$scope.amount -= 1;
console.log(binding)
}
$scope.plus = function (event) {
$scope.amount += 1;
}
},
templateUrl: '/client/views/swingsDirectiveView.html'
}
});
And finally my Controller:
app.controller("OtCtrl", ['$scope', function ($scope) {
$scope.Amount = 400;
$scope.Risk = 100;
setInterval(function(){
console.log($scope.Risk)
},2000);
}]);
I know that when I use ng-view, angularjs creates new scope. My issue that when I click plus or minus, the amount in the directive updates but the Risk model in the controller not, but on first load directive takes the risk init value and set the amount.
How can I fix this issue.
Thanks
I would suggest creating a model property in your controller like so:
app.controller("OtCtrl", ['$scope', function($scope) {
$scope.model = {
Amount: 400,
Risk: 100
}
}]);
Then, bind it to your directive via:
<div swings binding="model.Risk" title="model.Risk"></div>
What is likely happening is that scope inheritance is creating a copy of Amount and Risk (since they're primitives); whereas creating an object like this causes the reference to get copied, meaning the scope hierarchy shares the same data.

Resources