I would like to dynamically load a component. So I tried this approach but it didn't worked:
<page-{{current_page}}></page-{{current_page}}>
Currently I'm using this approach but it doesn't seems efficient:
<div *ngIf="current_page==1">
<page-1></page-1>
</div>
<div *ngIf="current_page==2">
<page-2></page-2>
</div>
...
This is not supported. String interpolation {{}} can only be used for property-values and element-content, but not for element-names or attribute-names.
Perhaps ViewContainerRef.createComponent() can do what you need.
For an example see Angular 2 dynamic tabs with user-click chosen components
If you have a limited set of components you want to display, *ngIf or ngSwitchCase is the way to go.
Related
I'm looking to build something like an expand collapse using Angular 1.5 Components. The idea is that you could have one or more of these in a row, or you could nest them to create a tree. So, valid html might look like:
<expand-collapse title="This is my title">
<p>This is my content</p>
</expand-collapse>
Or
<expand-collapse title="Level 1 Title">
<expand-collapse title="Level 2 Title">
<p>This is my content</p>
</expand-collapse>
</expand-collapse>
So, my question is whether or not I can do this with an Angular 1.5 Component (not Directive) in a way that the Level 2 expand-collapse could be aware of it's parent expand-collapse. Typically when you nest components like this I think you would have something like:
component('expandCollapse', {
...
require : {
parentCtrl : "^expandCollapse"
}
...
However A) nesting isn't REQUIRED in this case, and B) parentCtrl ends up being a never-ending recursive reference to the current $ctrl.
Is this something that can be done with Components? Or has it been explicitly banned for some reason?
I see only two way :
Define a directive for each level requiring the precendent level, this may lead to unnecessary code.
Search use angular functions : element.parent().controller('expand-collapse');. This approach is usually not recommended but I don't see anything simpler /cleaner than this.
I'm using Angular 1.x and I have a section of code that I'm looking to repeat quite a bit, so I wanna throw it in a directive. The trouble is, it's somewhat complicated and I'm not sure how to begin writing it.
Essentially, it's a section of the page that displays various card directive and with infinite scrolling and perfect scrollbar.
<perfect-scrollbar refresh-on-change="myScope.data">
<div class="limit-columns">
<masonry masonry-options="{gutter: 30, isFitWidth: true}">
<user-card class="masonry-brick" ng-repeat="item in myScope.data"></user-card>
</masonry>
<div class="infinite-scroller" infinite-scroll="myScope.showMore()" infinite-scroll-tolerance="5"></div>
</div>
</perfect-scrollbar>
Perfect-scrollbar and masonry are both angular libraries on GitHub. Infinite-scroller is one I wrote myself, but works as you'd expect.
myScope contains a data attribute that is a list of objects containing a card's data. myScope.showMore is a function that adds items to that myScope.data list. Perfect-scrollbar also takes the refresh-on-change attribute which watches for changes on a particular object, in this case the list.
Ideally my directive would look something like this:
<card-scroller gutter="30" tolerance="5">
<some-card ng-repeat="achievements.data"></some-card>
</card-scroller>
But I'm not sure how feasible this is. Thanks!
I have a need to use the same directive within a directive, depending on a conditional param. However, when ever i try to do it, it seems to go to an endless loop. As i understand, it tries to pre-load the templates and that causes an endless recursion and at the end, it just throws me the following error:"RangeError: Maximum call stack size exceeded".
I have created an example in fiddle.. as you can see in the example, when the param's value is "1", it creates the error (even when the second level param is valued as "2" so it shouldn't have real recursion issues in the controller/app).
https://jsfiddle.net/qh9nh1gx/
"custom-directive"'s template:
<div>
<div ng-if='info==1'><div custom-directive info='2'></div></div>
<div ng-if='info==2'>DONE,single.</div>
</div>
Thanks
I have found 2 options to deal with the issue, the first one, is exactly what Jju described - creating a new "compiler" method (it can be grabbed from the url he sent).
The second option - always using an additional template for the "recursive" parts of the directive. For example, in my directive, i had a "ng-repeat" part that depending on the items value, it could request to display the directive again. while i used "ng-include" to have the other directive, it worked.
<div ng-repeat="item in items" ng-include="'inline-possibly-recursive-template"'></div>
in that template, you can call the directive again without any issues..
I hope that it will anyone else that will stumble into that issue.
You can look into https://stackoverflow.com/a/19065910/1680674 that describe a common approach to create directive that use himself inside
I ran into this problem in several situations, but let's use one example here. Say I have an interaction flow of form submission. It is composed of three steps, for example, data input step, double checking step, and confirmation step. In each step, I will display different relevant information along with the form using ng-show/ng-hide. The way I do it now is to define the flow like a state machine and use a internal variable (e.g. currState) to represent the current state, and modify the variable when switching to a different state. In ng-show/ng-hide, I check the currState variable to show/hide the element. Something looks like this:
In my Angular controller:
$scope.currState = 'DATA_INPUT';
In my HTML:
<div ng-show="currState == 'DATA_INPUT'"></div>
I'm wondering if there is any native support for this kind of use case or best practices/patterns, since the way I'm doing now is error-prone and not very flexible. Thanks!
You can use ngSwitch for this:
http://docs.angularjs.org/api/ng.directive:ngSwitch
So:
<div ng-switch on="state">
<div ng-switch-default>Fist. <button ng-click="state='second'">Next</button></div>
<div ng-switch-when="second">Second. <button ng-click="state='final'">Next</button></div>
<div ng-switch-when="final">Final</div>
</div>
In angular I found out you can bind a template to a function which returns an array, like this:
<div class="cal_row" id ="id_{{task.id}}" ng-repeat="task in calendar.filtered()">
<div class="id">{{task.id}}</div>
<div class="task">{{task.task}}</div>
<div class="start">{{task.start}}</div>
<div class="finish">{{task.finish}}</div>
</div>
It's pretty cool, because that way I can, for example, avoid having to keep a variable around just to maintain the filtered version of the data.
However, I also loose the binding with the original data: when the underlying data changes, I can't seem to get angular.js to spot the change, and update the view.
Is there a way to do that? I tried to find anything in the docs, but couldn't
Thanks a lot
If you make a change to some data from outside angular, you have to use $myScope.$apply so angular knows something has changed. http://docs.angularjs.org/api/ng.$rootScope.Scope#$apply