AngularJS values - angularjs

How do I get the FirstName value in my directive?
<hello-World value="{{item.FirstName}}"> </hello-World>
app.directive('helloWorld', function() {
return {
restrict: 'AE',
replace: 'true',
template: '<h3>Hello ??????</h3>'
};
});

To get values you need to use scope parameter in directive. Read more from directives here https://docs.angularjs.org/guide/directive
Check this example
angular.module('myApp', [])
.directive('helloWorld', function() {
return {
restrict: 'AE',
replace: 'true',
template: '<h3>Hello {{value}}</h3>',
scope: {
value: '#'
},
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<hello-World value='World' />
</div>

app.directive('helloWorld', function() {
return {
restrict: 'AE',
replace: 'true',
template: '<h3>Hello {{value}}</h3>',
scope: {
value: '='
}
};
});

Related

Parent directive controller undefined when passing to child directive

I asked general question here in this post. I've got answer with working example; however when I try to use this example to modify existing code, I get error.
See my code below and in this Plunker page.
Html
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular.min.js"></script>
<div ng-app="myApp">
<tmp-menu ng-disabled="true">
<tmp-menu-link></tmp-menu-link>
<tmp-menu-link></tmp-menu-link>
</tmp-menu>
</div>
JavaScript(AngularJS):
angular.module('myApp', [])
.controller('MyDirectiveController', MyDirectiveController)
.directive('tmpMenu', function() {
return {
restrict: 'AE',
replace:true,
transclude:true,
scope:{
disabled: '=?ngDisabled'
},
controller: 'MyDirectiveController',
template: '<div>myDirective Disabled: {{ disabled }}<ng-transclude></ng-transclude></div>',
link: function(scope, element, attrs) {
}
};
})
.directive('tmpMenuLink', function() {
return {
restrict: 'AE',
replace:true,
transclude:true,
scope:{
},
required:'^^tmpMenu',
template: '<div>childDirective disabled: {{ disabled }}</div>',
link: function(scope, element, attrs, MyDirectiveCtrl) {
console.log(MyDirectiveCtrl);
scope.disabled = MyDirectiveCtrl.isDisabled();
}
};
})
function MyDirectiveController($scope) {
this.isDisabled = function() {
return $scope.disabled;
};
}
Inside directive tmpMenuLink, MyDirectiveCtrl is undefined.
Why is that?
You have a typo in your code:
required:'^^tmpMenu',
change it to
require:'^^tmpMenu',
Check this plunkr
https://plnkr.co/edit/DgyW3OFgr1GyAR8fuATi?p=preview
Because it's require not required.
angular.module('myApp', [])
.controller('MyDirectiveController', MyDirectiveController)
.directive('tmpMenu', function() {
return {
restrict: 'AE',
replace: true,
transclude: true,
scope: {
disabled: '=?ngDisabled'
},
controller: 'MyDirectiveController',
template: '<div>myDirective Disabled: {{ disabled }}<ng-transclude></ng-transclude></div>',
link: function(scope, element, attrs) {}
};
})
.directive('tmpMenuLink', function() {
return {
restrict: 'AE',
replace: true,
transclude: true,
require: '^^tmpMenu',
template: '<div>childDirective disabled: {{ disabled }}</div>',
link: function(scope, element, attrs, MyDirectiveController) {
scope.disabled = MyDirectiveController.isDisabled();
}
};
})
function MyDirectiveController($scope) {
this.isDisabled = function() {
return $scope.disabled;
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.3/angular.min.js"></script>
<div ng-app="myApp">
<tmp-menu ng-disabled="true">
<tmp-menu-link></tmp-menu-link>
<tmp-menu-link></tmp-menu-link>
</tmp-menu>
</div>

Required controller cannot be found when using $transclude in required controller

Simplified example of the code....
HTML:
<div ng-app="app">
<m-carousel>
<m-carousel-slide>foo</m-carousel-slide>
<m-carousel-slide>bar</m-carousel-slide>
</m-carousel>
</div>
JavaScript:
class CarouselDirectiveController {
constructor($transclude) {
$transclude(clone => {
// do something
}, null, 'slide');
}
}
class CarouselSlideDirectiveController {
$onInit() {
console.log(this.carousel);
}
}
function carouselDirective() {
return {
restrict: 'E',
replace: true,
controller: CarouselDirectiveController,
controllerAs: 'carousel',
template: '<div class="m-carousel" ng-transclude="slide"></div>',
transclude: {
slide: 'mCarouselSlide'
},
scope: {},
bindToController: true
};
}
function carouselSlideDirective() {
return {
restrict: 'E',
replace: true,
transclude: true,
controller: CarouselSlideDirectiveController,
controllerAs: 'carouselSlide',
template: '<div class="m-carousel-slide" ng-transclude></div>',
scope: {},
bindToController: true,
require: {
carousel: '^^mCarousel'
}
};
}
angular.module('app.carousel', [])
.directive('mCarousel', carouselDirective)
.directive('mCarouselSlide', carouselSlideDirective);
angular.module('app', ['app.carousel']);
This throws the following error:
https://docs.angularjs.org/error/$compile/ctreq?p0=mCarousel&p1=mCarouselSlide
However, if I comment out the $transclude(clone => {}, null, 'slide'); then all is good in the world... How do I access the transcluded content in a parent controller if the controller is required by another?
CodePen: http://codepen.io/anon/pen/KzdNRE?editors=1011
I figured out what this was way back when... If you use $transclude this way you have to remember to manually append the transcluded content. So...
$transclude(clone => {
// do something then...
$element.append(clone);
}, null, 'slide');

AngularJS directive: scope with named controller

I have the example below.
HTML:
<body ng-controller="MainCtrl as MgtCtrl">
<p>Hello {{MgtCtrl.name}}!</p>
<p>Result is {{MgtCtrl.result}}!</p>
<output-content data="MgtCtrl.name" result="MgtCtrl.result"></output-content>
</body>
JavaScript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var MgtCtrl = this;
MgtCtrl.name = 'World';
MgtCtrl.result = "no";
MgtCtrl.changeLabel = function() {
alert('changeLabel');
MgtCtrl.result = 'yes';
}
});
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
},
controller: 'MainCtrl',
controllerAs: 'MgtCtrl'
};
});
ouputContent.html:
<div>
{{data}}
<button ng-click="MgtCtrl.changeLabel()">Change</button>
</div>
Plunker is: http://plnkr.co/edit/BW8VDyCaRnRgxE8I9JJy
I would like the result to be 'yes' when I click on the 'Change' button.
It doesn't work because of the named controller.
Could you please explain to me how to write the directive to do so ?
Regards.
You never was binding the scope variables to the named controller in the directive.
You must add the attribute bindToController: true to the directive definition like this plunker:
http://plnkr.co/edit/2QdnkpeuTM6adG9KoyJT?p=preview
Directive code:
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
},
controller: 'MainCtrl',
controllerAs: 'MgtCtrl',
bindToController: true
};
});
This go to add the data and result binding to the respective directive controller.
I think in this case you don't need to specify controller in the directive.
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
}
};
});
Also html shoul be updated:
<body ng-controller="MainCtrl as MgtCtrl">
<p>Hello {{MgtCtrl.name}}!</p>
<p>Result is {{MgtCtrl.result}}!</p>
<output-content data="MgtCtrl.name" result="MgtCtrl.result" change-label="MgtCtrl.changeLabel()"></output-content>
</body>

AngularJS - accessing parent directive properties from child directives

This should not be too hard a thing to do but I cannot figure out how best to do it.
I have a parent directive, like so:
directive('editableFieldset', function () {
return {
restrict: 'E',
scope: {
model: '='
},
replace: true,
transclude: true,
template: '
<div class="editable-fieldset" ng-click="edit()">
<div ng-transclude></div>
...
</div>',
controller: ['$scope', function ($scope) {
$scope.edit = ->
$scope.editing = true
// ...
]
};
});
And a child directive:
.directive('editableString', function () {
return {
restrict: 'E',
replace: true,
template: function (element, attrs) {
'<div>
<label>' + attrs.label + '</label>
<p>{{ model.' + attrs.field + ' }}</p>
...
</div>'
},
require: '^editableFieldset'
};
});
How can I easily access the model and editing properties of the parent directive from the child directive? In my link function I have access to the parent scope - should I use $watch to watch these properties?
Put together, what I'd like to have is:
<editable-fieldset model="myModel">
<editable-string label="Some Property" field="property"></editable-string>
<editable-string label="Some Property" field="property"></editable-string>
</editable-fieldset>
The idea is to have a set of fields displayed by default. If clicked on, they become inputs and can be edited.
Taking inspiration from this SO post, I've got a working solution here in this plunker.
I had to change quite a bit. I opted to have an isolated scope on the editableString as well because it was easier to bind in the correct values to the template. Otherwise, you are going to have to use compile or another method (like $transclude service).
Here is the result:
JS:
var myApp = angular.module('myApp', []);
myApp.controller('Ctrl', function($scope) {
$scope.myModel = { property1: 'hello1', property2: 'hello2' }
});
myApp.directive('editableFieldset', function () {
return {
restrict: 'E',
scope: {
model: '='
},
transclude: true,
replace: true,
template: '<div class="editable-fieldset" ng-click="edit()"><div ng-transclude></div></div>',
link: function(scope, element) {
scope.edit = function() {
scope.editing = true;
}
},
controller: ['$scope', function($scope) {
this.getModel = function() {
return $scope.model;
}
}]
};
});
myApp.directive('editableString', function () {
return {
restrict: 'E',
replace: true,
scope: {
label: '#',
field: '#'
},
template: '<div><label>{{ label }}</label><p>{{ model[field] }}</p></div>',
require: '^editableFieldset',
link: function(scope, element, attrs, ctrl) {
scope.model = ctrl.getModel();
}
};
});
HTML:
<body ng-controller="Ctrl">
<h1>Hello Plunker!</h1>
<editable-fieldset model="myModel">
<editable-string label="Some Property1:" field="property1"></editable-string>
<editable-string label="Some Property2:" field="property2"></editable-string>
</editable-fieldset>
</body>
You can get access to parent controller by passing attribute in child directive link function
link: function (scope, element, attrs, parentCtrl) {
parentCtrl.$scope.editing = true;
}

Directive and scope in AngularJS

Here is the code, ideally i should see
parent: true
when I click the toggle
However, it doesn't work
Here is the plunker
<body ng-controller="MainCtrl">
<button type="button" ng-click='isParentShown= !isParentShown' >Toggle</button>
<div><span>Controller-isParentShown: {{isParentShown}}</span></div>
<parent isShown='isParentShown'></parent>
</body>
var app = angular.module('plunker', []).directive('parent',function(){
return {
restrict: 'E',
replace: true,
scope: {
isShown: '='
},
template: '<span>Parent: {{isShown}}</span>'
};
}).directive('child',function(){
return {
restrict: 'E',
replace: true,
template:'<span>Child: {{isChildShown}}</span>',
scope: {
isChildShown: '#'
}
};
});
app.controller('MainCtrl', function($scope) {
$scope.isParentShown = false;
});
The problem is in the casing of the attributes, if you define a isShown binding, it's expecting a is-shown or is:shown attribute. Here's the fixed plunker: http://plnkr.co/edit/UOigth

Resources