I've a two directives with transcluding html which calls isolated scope.
This Plnkr works fine while templates are inline, but if I change template to templateURL, it stops work.
Are there any issues with compiling?
Loading the template use URL, Angularjs creates an additional transcluded scope I guess.
Try to use $$prevSibling.$$prevSibling to access the functions.
Btw, it is really hacky to use $$prevSibling.
<div authorization>Sign in</div>
<div registration>Registration</div>
Related
Let's say I am using a custom directive named my-form-data:
<my-form-data info='infoObj1' template="ssc.html"/>
<my-form-data info='infoObj2' template="college.html"/>
Inside directive definition, I want a different templateUrl based on the template attribute of the directive on the HTML page.
Is there any way to specify the controller class associated with ssc.html and college.html?
Use different directives. Its just a couple lines of code and they'll have their own template HTML. They can all share the same controller if desired or have their own. It doesn't make sense to try and use the same directive if you have different views and different controllers.
To answer your question directly, you can specify the controller in your directive HTML using ng-controller.
ssc.html
<div ng-controller='sscCtrl'>
...
</div>
college.html
<div ng-controller='collegeCtrl'>
...
</div>
I had the intention to use one template across several views having different controllers.
But now I realize that I cannot just write universal binding in templates because values will be put inside $scope.concreteControllerName.
Angular docs for ngInclude say that
This directive creates new scope.
I could use ng-init directive and pass controller instance to template's scope:
<ng-include src="..." ng-init="controller=concreteControllerName"/>
or even better
<ng-include src="..." ng-init="model=getModelForTemplate()"/>
and then write {{controller.boundvalue}} in template.
That is a working solution, I guess.
And here I'd like to know whether other better approaches exist and if not, should templates always be used with some notion of passed model to abstract away from parent scope?
Use John Papa's controllerAs View Syntax and controllerAs with vm. You specify different controllers in the ng-include directives but use the same src html template. The common vm variable name is used in the template.
index.html
<div ng-include ng-controller="controllerOne as vm" src="'same.html'"></div>
<div ng-include ng-controller="controllerTwo as vm" src="'same.html'"></div>
<div ng-include ng-controller="controllerThree as vm" src="'same.html'"></div>
controllerOne.js
function controllerOne() {
var vm = this;
vm.name = 'Controller One!';
sharedTemplate.html
<div>{{vm.name}}</div>
Here is a full working version: Full Working Code in Plunker
Following the advise of this answer, I've been trying to render a controller and template manually, but I can't get it to work when the template contains an ng-switch directive. Any ideas?
Here's the fiddle: http://jsfiddle.net/kynZm/
It looks like the ng-switch directive was being compiled before my link function had a chance to run and was linking to the $rootScope. Moving the $compile call to the compile phase of the directive seemed to do the trick.
http://jsfiddle.net/z8uXg/
I am trying to make a transitive transclusion, or call it “directive inception”.
I made this example to illustrate what I am trying to do:
http://plnkr.co/edit/0hFFHknDps2krtK1D9ud?p=preview
The directive “first” wraps the directive “second” in its template and the two of them use transclusion.
What I want to do is to bind a value from a controller to the html that is a child of the “first” directive.
So I wanted my example to display:
<h1>Chained transclusions test</h1>
<div>
<h2>First directive</h2>
<div>
<h2>Second directive</h2>
<div>Controller hello</div>
</div>
</div>
Obviously that is not what I got.
I tried to analyze the scope with the developer tool and I was surprised by the result scope tree:
the result trees
I thought angularJS would create a new scope when using the transclude feature in a directive. And that this scope would be a non isolate sibling of my directive isolate scope. But I cannot see any sibling of my first directive scope (although it uses transclude). Plus, every children of my “first” directive has a scope isolated from the controller scope since the “first” directive scope is an isolated one.
I don’t understand the behavior here.
Is the transclude inclusion completely forbidden in angularJS ?
Is it possible to create a directive with transclusion, that wraps another directive that uses transclusion ?
It seems to me that this is the whole power behind web components, the fact that transclusion or any other special caracteristics should be seen as “implementation detail”, and the component should be able to use other directives that hide their own implementation details.
Without getting into the details of scope creation when using isolate scope with transclusion... it is possible to nest transclusions, but in your example, you need to make scope.controllerMsg available to the first directive's isolate scope:
JS:
app.directive('first', function(){
return {
...
scope: { controllerMsg: '=text'},
...
}
});
HTML:
<first text="controllerMsg">
{{controllerMsg}}
</first>
Demo
I'm reading the directives section of the developers guide on angularjs.org to refresh my knowledge and gain some insights and I was trying to run one of the examples but the directive ng-hide is not working on a custom directive.
Here the jsfiddle: http://jsfiddle.net/D3Nsk/:
<my-dialog ng-hide="dialogIsHidden" on-close="hideDialog()">
Does Not Work Here!!!
</my-dialog>
<div ng-hide="dialogIsHidden">
It works Here.
</div>
Any idea on why this is happening?
Solution
Seems that the variable dialogIsHidden on the tag already make a reference
to a scope variable inside the directive and not to the variable in the controller; given
that the directive has it's own insolated scope, to make this work it's necesary to pass
by reference the variable dialogIsHidden of the controller to the directive.
Here the jsfiddle:
http://jsfiddle.net/h7xvA/
changes at:
<my-dialog
ng-hide="dialogIsHidden"
on-close="hideDialog()" dialog-is-hidden='dialogIsHidden'>
and:
scope: {
'close': '&onClose',
'dialogIsHidden': '='
},
You're creating an isolated scope inside your directive when asigning an object to scope. This is why $scope.dialogIsHidden is not passed through to the directive and thus the element is not being hided.
Kain's suggested adjustment for the fiddle with using $parent illustrates this.
your can change the
<my-dialog ng-hide="dialogIsHidden" on-close="hideDialog()">
to
<my-dialog ng-hide="$parent.dialogIsHidden" on-close="hideDialog()">