Angular Transclusion - angularjs

See this plnkr
https://plnkr.co/edit/theggRtJlbFj1H4zVUKU?p=preview
using the $compile service, I need to have dirC nested inside dirB.
The output should be
DirB
DirC
I thought this was bug since dirC directive and controller was never fired, so the Angular group said to use transclusion.
Ok, so I use transclusion and dirC and dirB is never added to the DOM.
What am I missing?

The directive C is included inside the directive B. But the only visible text in both templates is inside the div which has the directive ng-transclude. So the textual content is replaced by the transcluded HTML: the directive C in the case if <dir-b>, and nothing in the case of <dir-c>.
Here's your example with fixed templates to show you that it works fine: https://plnkr.co/edit/FRtMA3h0Caredc4staW8?p=preview
Like ng-view, ng-transclude is a placeholder which means: replace the content of this element by the one inside the body of the directive.

Related

How do I know if directive is enclosed in a container with ng-if = false?

I am developing a custom directive and now I need to handle ng-if. This is easy enough when ng-if is on the directive it self. However when ng-if is on an enclosing container element my compile function fails with run time errors.
Question is: what is the best and most efficient way to know, inside the compile function of a directive, that the directive is enclosed within a container with ng-if is false OR an expression that evaluates to false.
For example:
<div ng-if="false">
<my-directive></my-directive>
</div>
And another example:
<div ng-if="somescopeValue > 300">
<my-directive></my-directive>
</div>
Maybe the answer is using jquery to traverse the dom and find a parent with
an ng-if attribute but I was wondering if there is another more "angular" way of doing this.
Your directive shouldn't rely on knowing whether it is encapsulated in a ng-if expression. That breaks the principle of 'Separation of Concerns' and deteriorates code re-use. Consider redesigning your custom directive in such a way that it needs not be aware of its host elements, in the same fashion that all components (should) work.
If you are using same scope as parent controller or directive then you are able to access same variable in your directive(here my-directive) also. If this is not a case then you need to write code to access parent element in link function of my-directive. You will get directive element in link function as a parameter.
I'm not sure how the error happens, because when your directive is inside ng-if="false", your directive won't get called at all - all compile, link and controller function in the directive will only run as soon as your directive gets added in DOM.
Perhaps your error can be solved by initializing something in case your directive is not added.

isolate scope within directive doesn't behave as expected

I'm creating a test directive as can be seen here:
http://jsbin.com/xosusozipufe/1/
This isn't behaving as expected. I thought the h4 within the directive div would read 'within the app Hello World' on load and then the end would change as the buttons were clicked. The html nested within the directive div doesn't inherit the isolate scope of the directive, is this correct?
Any thoughts appreciated
C
# isolated scope is one way and works in up-down fashion that means whatever you pass that will go as string so you can not update from scope of directive.
Either you should use transclude or put html of directive inside template/templateUrl option.
If you want update from directive scope then either you can use "=" isolated scope or you can pass function with "&" isolated scope.
JSBin Demo

AngularJS manually render controller and template containing ng-switch directive

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/

Why ng-hide doesn't work with custom directives?

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()">

Angular JS: scope not correct when calling a function dynamically?

I'm new to Angular JS. In my plunkr, I have a typeahead that works when I have the typeahead in the html markup. However, when I dynamically generate the html inside my directive, the typeahead no longer works.
Code Here:
http://plnkr.co/edit/KdrxptYAnpTmKa7ZuKkM?p=preview
and to take it one step further, when I pass in a function, it still does not work:
http://plnkr.co/edit/jqN913hJxuVSFAZxAQt7?p=preview
It is not a trivial problem you are trying to solve here, I'm afraid. Basically you are bumping into the scoping issue. The typeahead directive evaluates it expression (city for city in cities($viewValue) here) in the scope of the DOM element on which it is placed. The way you written your wrapper directive makes it so the expression is evaluated in the directive's scope which is isolated and doesn't "see" your controllers scope.
The are number of ways around it but probably the simplest one is to link your $compiled-ed element in the scope that is $parent of your directive scope:
var linkedInput = $compile(inputHtml)(scope.$parent);
Here is a working plunk: http://plnkr.co/edit/fLFwIKNqIRbnesMjZBGj?p=preview
The other alternative is to loose an isolated scope and "manually" take care of the 2-way data binding with the help from the $parse service.

Resources