Angularjs Directive -> child directive variables with transclusion - javascript

I'm making a complex view with a parent directive, and some sub-directives nested in. I've run into a problem where it seems like variables aren't being passed through the layers of directives properly.
Here's the setup:
<header>
<div expandable expand="functionFromHeader">
<div votable show-vote="variableFromHeader">
...
<!-- from votable template -->
<vote>
<!-- from vote template -->
<div class="vote" ng-show="showVote">vote</div>
</vote>
</div>
</div>
<div class="contentGettingExpanded" ng-show="variableFromHeader">
...
</div>
</header>
Both the expandable directive and the votable directive use transclusion.
The function from the header scope "functionFromHeader" toggles the variable "variableFromHeader".
The problem is the variable starts out false, but the votes show up anyway. (In the link function I inspected it an it is coming through as a string "variableFromHeader" rather than the value of the variable.
The content that is supposed to expand and collapse, starts collapsed as it should, but once it is expanded, it doesn't collapse. The content just flashes on the screen.
How do I properly pass the variables through the directives?

Related

How do i change the class of container to container-fluid when change the uiview using angular ng-class?

Am a Starter in angularjs. Having 5 more pages controlled over uiview to get the pages.
I need to change the style from container to container-fluid where i used uiview in index page.
In html,
<div class="container" ui-view> </div>
For only one page i need to change the class to container-fluid.
I tried like this.
In html,
<div ng-class="{container-fluid: clearance}" ui-view> </div>
In controller i mentioned,
$scope.clearance= true;
It does not renders the ngclass. Can anyone please help on this.
An object property name can't have a - in it without quoting that whole name
Try
<div ng-class="{'container-fluid': clearance}" ui-view> </div>
Also depends which controller you are referring to. If it is the controller referenced in the routing config, then it will only have scope inside the ui-view

Is it possible to Angularjs ng-switch does not re render view?

In some page of my site, i have some directives inside ng-switch, like this:
<div ng-switch="contentMenuObj.model">
<div ng-switch-when="calendar">
// Some directive
</div>
<div ng-switch-when="history">
// Some directive
</div>
</div>
Every time that I change the "view" (calendar to history) and go back (history to calendar) the angular re-render the calendar view and new queries are make in the server.
My question is about this behavior, is it possible to angular does not re-render the views? If impossible, what is the best way to solve this problem?
If I understand correctly. You would like to not rerender view when contentMenuObj.model change - right? If so apply one way binding
<div ng-switch="::contentMenuObj.model">
<div ng-switch-when="calendar">
// Some directive
</div>
<div ng-switch-when="history">
// Some directive
</div>
</div>
Model in that case will be loaded only once.
Or try to use ng-show / ng-hide directives if you would like to load directives only once.
<div ng-show="contentMenuObj.model == 'calendar'">
// Some directive
</div>
<div ng-show="contentMenuObj.model == 'history'">
// Some directive
</div>
Angular re-render your directives because ng-switch remove div when ng-switch-when condition is not satisfied, which makes directive is destroy and next time must be re-render.
The ng-show directive in contrast to ng-switch directive not remove element, but only hides.
So, if you want to hide and show content without re-rendering, try:
<div>
<div ng-show="contentMenuObj.model === 'calendar'">
// Some directive
</div>
<div ng-show="contentMenuObj.model === 'history'">
// Some directive
</div>
</div>

Angular 1.5 nesting components

I have a container component that has 2 other controllers nested in it. I have them set up like so
container -> component1 and container -> component2
My train of thought here was that I could transclude the HTML from my page into my container component.
<container> <component1></component1> <component2></component2></container>
and then in the container HTML <div ng-init="vm.init()" ng-transclude></div>
Problem is, my container isn't running at all, I added a console log to its init function and no code is running. While component1 and component2 run their init's.
Seems to be a large amount of documentation covering older angular versions. Which tell me that they need to be nested like so <div ng-controller="parentController"> <div ng-controller="childController"></div> </div
How do you nest components into each other in 1.5?
Looks like the issue was that I was attempting to put a ng-init and ng-transclude in the same element. My guess is that ng-transclude overrides everything in the element it is on.
so I moved the ng-init to another element and its working fine
<div ng-transclude ng-init="vm.init()"></div>
changed to
<div ng-init="vm.init()"> <section ng-transclude ></section> </div>

Multiple partial views on AngularJS

I have an AngularJS application that has a list of contents on the menu. When the user clicks on an item on the menu, the content loads on the main view. There are multiple content types:
When "1" is clicked, a video is loaded. When "2" is clicked, a PDF document is loaded, and so on. Content types may repeat and be complex.
Now, I am setting $scope.content when an item is clicked and, depending on its contentType, I'm calling a different directive:
<div class="content" ng-switch on="content.contentType">
<div ng-switch-when="video">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-switch-when="pdf">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-switch-when="...">
<...-directive content="content"></...-directive>
</div>
</div>
Now I have two problems:
When the page is loaded, all the directive templates are automatically loaded. Even if I don't have a PDF in the menu, the pdf template and scripts will be loaded.
Searching for it, I learned that directives should be tiny, not entire modules of my app.
How do I rewrite the switch above so I can comply with the best practices and load the templates and scripts only when needed?
This is exactly what UI-Router is for: Angular UI Router
Decent tutorial on scotch.io
An easier drop-in replacement for your code may be to simply use ng-if. Ng-if won't instantiate the directive until it's called. Just make sure that your directives aren't transcluding the outer div- if that's the case, shut transclusion off, or add another div to wrap them.
<div class="content">
<div ng-if="content.contentType=='video'">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-if="content.contentType=='pdf'">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-if="content.contentType=='...'">
<...-directive content="content"></...-directive>
</div>
</div>

emberjs - Conditionally rendering templates within a larger template

Ember Community Assemble!
I want to conditionally {{render ''}} small templates inside of the application.hbs sidebar but the content of that sidebar depends on which model's hbs we are routed to. For instance, the contents of the 'permit' sidebar would be different than that of the 'profile' sidebar.
Right now I am only able to render all of the sidebar contents at once regardless of what model.hbs is chosen.
<!-- Right Sidebar in application.hbs START -->
<div id="sidebar-wrapper" class="super-super-float-right-col">
<div id="sidebar-wrapper" class="super-float-right-col">
<div id="sidebar-wrapper" class="float-right-col">
{{render 'applicant'}} <!-- only available to '/person/#' -->
{{render 'location'}} <!-- only available to '/permit/#' -->
</div>
</div>
</div>
<!-- Right Sidebar END -->
<div class="The rest of the content">
{{outlet}} <!--inserts the rest of the html into the main content container -->
</div>
I don't want both 'applicant' and 'location' to be rendered at the same time as they are above, and I want to data inside of 'applicant' to change depending on the id # of 'person'. The same relationship applies to 'location' inside of 'permit.hbs'
VpcYeoman.PermitRoute = Ember.Route.extend({
renderTemplate: function() {
this.render({ render:'location'});
}
});
Application_route.js is blank for now
Although 1.2.0 introduced the ability to use properties for template name in {{view}} it does not work for {{render}} yet.
So your options are to use {{view}} if you can, or a series of {{#if}} in the template, or a component/view to wrap the choice of what to render (one way to do this would be to have a template for each render, and a choice view that binds templateName property to the parentController property that determines which should be displayed)
Here is a jsbin that I used to experiment.

Categories