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
Related
I've been a C/C++ coder for a long time, but am new to Angular2 and TypeScript. I have a TypeScript class (call it Node) which has a type: string property that specifies what sort of node it is. (The data comes as JSON from a server, and is basically being parsed out as a syntax tree.)
What I'm doing now in the view template in order to choose the view for each Node object is using an ngSwitch to check the value of node.type, and then inserting the appropriate selector using ngSwitchCase for each possible case, e.g.:
<div [ngSwitch]="node.type">
<node-type-a-view *ngSwitchCase="'a'" [(node)]="node"></node-type-a-view>
<node-type-b-view *ngSwitchCase="'b'" [(node)]="node"></node-type-a-view>
<node-type-c-view *ngSwitchCase="'c'" [(node)]="node"></node-type-a-view>
<div class="debug" *ngSwitchDefault>
TODO: View for type "{{node.type}}" is missing
</div>
</div>
The problem is that there are over a hundred different node types, and so this is going to be very unwieldy, very quickly.
What I'd like to do is something like this (but obviously this doesn't work in Angular2):
<node-type-{{node.type}}-view [(node)]="node"></node-type-{{node.type}}-view>
Or, using an attribute selector:
<div node-type-{{node.type}}-view [(node)]="node"></div>
Is there any functionality that comes close to what I'm looking for? I don't need to dynamically create the node-type-*-view views themselves, just the template that references them.
Also, apologies if I'm getting this architecture completely wrong. I'm still wrapping my head around the way Angular2 does things!
Thanks for any assistance you can give!
I'm stil learning Angular so forgive me if the question is nonsense
I have an object with this hierarchy:
{
a : [...],
b : [{
a: [...]
}, {
...
}]
}
That is I have the same object model for direct children and indirect children of the main object. That is, the two properties named "a" have the same fields
I built a view that is managed with ng-view, and thought that could be called in the main controller and in the ng-repeat that iterates through b elements. However, I don't know how to change the scope that is passed to the view managing "a":
The main view is made in this way:
<div ng-controller="MainController as ctrl">
<div ng-include="'subView'"/>
<div ng-repeat="bElement in ctrl.b">
<div ng-include="'subView'"/>
</div>
</div>
In subView, i can access element like bElement.a because I get the same scope as the outer controller. But how to access property a of the root element?
What I would need, is to have something like ng-repeat that permits to create an alias to a property so that it can be overridden, but without the "repeat".
I tried also using ng-init in this way:
<div ng-controller="MainController as ctrl">
<div ng-include="'subView'" ng-init="list = ctrl.a"/>
<div ng-repeat="bElement in ctrl.b">
<div ng-include="'subView'" ng-init="list = bElement.a"/>
</div>
</div>
but only the second invocation works
Above code should work, but the only thing which I can see here missing is, you haven't closed below ng-include div correctly. So it stops browser will not consider the exact next div & the innner ng-repeat div will not get render.
<div ng-include="'subView'" ng-init="list = ctrl.a"/>
So it should be closed the div correctly, so that the next element on same will taken by browser.
<div ng-include="'subView'" ng-init="list = ctrl.a"></div>
Sample Plunkr of above issue.
Solved working Plunkr list variable updated in child.
Though it will work, I'm seeing some architectural threat in current implementation, because current implementation looks very tightly coupled. Any small change in requirement could lead to re-work on it. As ng-init may harm you in future. If suppose your collection is going to update in specified time of interval(at that ng-init expression will not evaluated on second time rendering of template)
I know this sounds like a really simple issue, but this is driving me a little nutty.
I have an observable array of objects that I would like reflected in my html. So for each object in the html I would like to show a paragraph on the page. To do this I'm setting up the array in my viewModel
createViewModel: function(){
var viewModel = kb.viewModel(this.model,{});
viewModel.Objects = ko.observableArray(this.model.models);
return viewModel;
},
and that array looks like this.
And then later on in the file I am applying my Binding for the page. I know this is working because I have other binding on the page not breaking. Just this one.
My html looks like this. I'm just trying to loop through the objects and show that p tag for each object.
<div data-bind="foreach: Objects">
<p>here</p>
</div>
I've tried just about everything I can think of. I've added ()'s after the Objects, I've read the docs from top to bottom and have read every thread that has had this issue. But nothing seems to work. Most of them say it's something wrong with the applyBindings, but that's the one thing I know is right.
Is there any way to fix this? Any help is appreciated!
It's difficult to help you with out the whole sample. But I try to give some advice which helps me in the similar situation. First of all install plugins Knockoutjs plugins. The second try to change
foreach: Objects
to
foreach: $data.Objects
If error dissapear it mean you try to bind to other object not to your viewModel.
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 have an angular app that shows a list of things
<div ng-repeat="thing in things" regular-thing>
implemented with an ng-repeat that shows a regularThing directive for each thing in my list.
It's actually a little bit trickier than that though:
<div ng-repeat-start="thing in things">
<div ng-if="$first || thing.isSpecial" special-thing></div>
<div ng-if="!$first && !thing.isSpecial" regular-thing></div>
</div>
<div ng-repeat-end></div>
I use a different directive for the first thing in my list, and also for any "special" things. For our purposes, a thing becomes "special" when the user clicks on it - so, as they're scrolling through the list, they can click on a thing to have it displayed in a different (more extensive) template.
The way I have it now feels wrong to me. For one thing, I really don't need to have two different directives - just different templates. The logic is identical, specialThing just has a bit more of it. For another thing, I'm toggling a property on the data (namely thing.isSpecial) for purely view-related reasons, which makes me die a little bit inside.
So my question: Don't I deserve to die a little bit inside for this? Isn't there a cleaner, more "angular" way to handle this (i.e. to toggle between the directive templates)?
First, no one deserves do die. So the answer to your question is "no".
But you do raise some interesting points.
First, it's ok to have "view model" information in your scope (or controller, depending on if you are using the ControllerAs syntax or not). However, you definitely don't want to add view model information to your data models. Here's how I might do it (using your click-toggles-something-special example).
<div ng-repeat-start="thing in things">
<div ng-if="$first || isSpecial" ng-include="/specialtemplate.html" ng-click="isSpecial = !isSpecial"></div>
<div ng-if="!$first && !isSpecial" ng-include="/regulartemplate.html" ng-click="isSpecial = !isSpecial"></div>
</div>
<div ng-repeat-end></div>
The key difference is I'm adding the isSpecial property to the scope, not to thing, and isSpecial will be specific to that particular ng-repeat item's scope.
Also, unless you're planning on doing DOM manipulation, you can replace them with ng-include + ng-controller in the template html.
Some people prefer that pattern (include + controller) instead of directives, and other prefer to go ahead and others prefer to go ahead and write directives because it's more "componenty" (I made that word up). I think either is a valid way to go.