Error: $update is not a function - angularjs

I have nested tree pages in the mean.io angular controller from mongo db:
{"_id":"54a67318250272254669fa93","name":"test page 1","parent":null,"active":true,"children":[{"_id":"54a67326250272254669fa94","name":"test page 1.1","parent":"54a67318250272254669fa93","active":false,"children":[{"_id":"54a67330250272254669fa95","site":"54a6730a250272254669fa92","name":"test page 1.1.1","parent":"54a67326250272254669fa94","active":false,"children":[]}]}]}
Then I show it like this:
<ol>
<li data-ng-repeat="page in pages" data-ng-include="'renderer.html'">
</li>
</ol>
and it is a renderer.html:
<input type="checkbox" data-ng-model="page.active" data-ng-change="pageActive(page)" />
<ol data-ng-model="page.children">
<li data-ng-repeat="page in page.children" data-ng-include="'renderer.html'">
</li>
</ol>
this is code in the controller
$scope.pageActive = function (page) {
if (!page.updated) {
page.updated = [];
}
page.updated.push(new Date().getTime());
page.$update();
};
ok, my proplem:
then I click to checkbox and call pageActive function - I have error in the firebug (because nestet object has no update function):
Error: page.$update is not a function
but then i click to checkbox not in the nestet pages - it works
because my nested page model is overwriting parent model

Try changing
<li data-ng-repeat="page in page.children" data-ng-include="'renderer.html'"></li>
To
<li data-ng-repeat="childPage in page.children" data-ng-include="'renderer.html'"></li>
I don't know what you are referring to with page, but by using data-ng-repeat="page in page.children" you are overwriting whatever it is with the ng-repeat child, which does not have the function $update (hence it's undefined).

Related

How to refer DOM elements ID using "a href" inside views - Angular JS

I have tried to find some solution on google about this but couldn't get an exact answer.
I am trying to change tabs inside a view using below code:
<ul class="nav nav-tabs">
<li class="{active: selectedTab === 'details'}"><a href ng-click="selectTab('details')">Details</a></li>
<li class="{active: selectedTab === 'size'}"><a href ng-click="selectTab('size')">Size</a></li>
<li class="{active: selectedTab === 'shipping'}"><a href ng-click="selectTab('shipping')">Shipping</a></li>
</ul>
But whenever I am clicking on "Size" tab, the view redirects to some page. I mean URL changes
from http://localhost:8080/abcd/index.html#/ TO http://localhost:8080/Final_Albatross/index.html#/size
Without view implementation, the click refers to id "size" and tab changes.
Definitely angular is treating this click as a new view call. Please help me out!!
My JS file:
mainAngular.controller('ProductDetailController', function($scope, $routeParams) {
$scope.prod_Id = $routeParams.prodId;
$scope.selectTab = function(tabName) {
alert(tabName);
$scope.selectedTab = tabName;
alert($scope.selectedTab);
}
});
Although I have achieved it using "target="_self" but I want to do it in angular way.
Using anchor links in Angular require target="_self".
https://docs.angularjs.org/guide/$location
<ul>
<li>Link</li>
<li>Anchor</li>
</ul>
Forget about the jQuery, DOM way to handle that kind of problems. Use the angular way.
In AngularJS, the single point of truth is the model. The view (i.e. the HTML) is only a representation of that model, that changes automatically when the model changes.
So, you want a selected tab. Add that to the model:
$scope.selectedTab = 'details';
You want to be able to change which tab is selected. That is as simple as
$scope.selectTab = function(tabName) {
$scope.selectedTab = tabName;
}
And you want the view to be reflect the model values:
<ul class="nav nav-tabs">
<li class="{active: selectedTab === 'details'}"><a href ng-click="selectTab('details'}">Details</a></li>
<li class="{active: selectedTab === 'size'}"><a href ng-click="selectTab('size'}">Size</a></li>
</ul>

Angularjs How to update partial template

I would like to know how to make controller function work whenever I change the state.
This is the main template of my Angular app:
<div>
<div ng-include="'/navigation.html'"></div>
<div>
<!-- Page wrapper -->
<div ng-include="'/topnavbar.html'"></div>
<!-- Main view -->
<div ui-view></div>
<!-- Footer -->
<div ng-include="'/footer.html'"></div>
</div>
</div>
In navigation panel I have ng-repeat:
<ul ng-controller="NavigationCtrl" class="nav nav-second-level">
<li ng-repeat="user in users" ui-sref-active="active">
<a ui-sref="account">{{user.name}}</a>
</li>
</ul>
So, whenever I change the state, I would like to update this scope var users.
I think this is well known problem, but I am new in Angular so help me please.
Well, I see two ways here:
1) Listening for state events, and do callback that updates user data. Docs here: https://github.com/angular-ui/ui-router/wiki#state-change-events
2) I assume that users array comes from service, something like:
...
$http.get('/users', function(data){
return data;
});
...
so, instead of this, you can store an array locally in service(which is singleton), and update it from any places, it that way you'll have a link to array in 'NavigationCtrl', and data will be updated there as well.
What I mean:
function UserService($http) {
var users = []; //inital array
var updateUsers = function() {
//get to update users here
};
var getUsers = fucntion() {
return users;
}
return {
updateUsers : updateUsers, //this method will be called when you need to update user list
getUsers : getUsers //this method will be called in NavigationCtrl
}
}
Update:
Here what I meant in pt.2 http://plnkr.co/edit/U2XwXNEqAxRrEa0VpYAu?p=preview

Submit and disable all buttons in an ng-repeat without adding a new property on the scope

I have a list of items where each item is clickable and should trigger the submit(id) function. I would like to disable all items (buttons) when one of them is clicked.
<ul>
<li ng-repeat="item in items">
<button ng-click="submit(item.id)">Submit</button>
</li>
</ul>
I could define $scope.submitted variable in a controller and then set ng-disabled="submitted" in my view. I could also wrap it into a <form> and use frm.$submitted. Well... I would like to define everything inside view.
I search for an elegant solution where a don't have to define a $scope variable to achieve this. What do you propose?
If you do not want to define a property in the controller, and assuming that submit function never fails to submit. You could utilize the items array itself, by adding a property when click happens and after submit function is run.
<ul>
<li ng-repeat="item in items">
<button ng-click="submit(item.id); items.submitted=true"
ng-disabled="items.submitted">Submit</button>
</li>
</ul>
With this you are adding a property in the array items (so that it is available across child scopes of ng-repeat as well as items is set on its parent scope) so essentially you are not defining a new scope variable for this.
angular.module('app',[]).controller('ctrl', function($scope){
$scope.items = [{id:1},{id:2},{id:3},{id:4}]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="item in items">
<button ng-click="submit(item.id); items.submitted=true"
ng-disabled="items.submitted">Submit</button>
</li>
</ul>
</div>

angular-ui-router dynamic menu: TypeError: Cannot call method 'match' of undefined while rendering menu

i am new to angular and angular-ui-router and trying to create a menu.
I tried angular-ui-router and think that it fits for my needs.
now i have a problem while creating the menu with the ui-router attributes.
my html code looks like that:
<div ng-controller="MenuCtrl">
<ul>
<li ng-repeat="item in menu">
<a ui-sref="cf.{{item}}">{{item}}</a>
</li>
</ul>
</div>
the menu array contains different entries dependent on the info if the user is logged in.
now i get this error message:
TypeError: Cannot call method 'match' of undefined
<a ui-sref="cf.{{item}}" class="ng-binding">
It looks like ui-router tries to get access to the list entry before it is rendered complete with ng-repeat.
What can i do to prevent this problem?
So ui-router doesn't support interpolation in ui-sref, believe me I wish they would. Here is how I solved this.
In your controller:
app.controller("MenuCtrl", ['$scope', '$state', function($scope, $state) {
$scope.$state = $state;
}]);
In your view use an ng-href to evaluate $state object that we've now added to the $scope:
<div ng-controller="MenuCtrl">
<ul>
<li ng-repeat="item in menu">
<a ng-href={{ $state.href('cf.' + item) }}>{{item}}</a>
</li>
</ul>
</div>
You can also you this technique for wildcard params:
ng-href="{{ $state.href('cf.items.item', {'item' : item} ) }}"
Assuming you've set up your ui-router routes properly for this.

Angular : How to load images through XHR request in ng-repeat loop

I am trying to create a contact book in which every person can have a photo.
As I would like to display the contact before getting its photo, I would write something like
<ul>
<li ng-repeat="person in persons">{{person.firstname}} {{persone.lastname}}</li>
</ul>
I would try to call a get_photo(person) available in my scope.
<ul>
<li ng-repeat="person in persons">{{person.firstname}} {{persone.lastname}}
<img ng-src="{{get_photo(person)}}" />
</li>
</ul>
Which doesn't work because it binds the function to ng-src and call get_photo every time ng-repeat is called.
I finally tried to call get_photo when initializing the DOM element and store the result in a specific attribute photo
<ul>
<li ng-repeat="person in persons">{{person.firstname}} {{persone.lastname}}
<img ng-init="get_photo(person)" ng-src="{{person.photo}}" />
</li>
</ul>
$scope.get_photo = function (person) {
// Simple example; I will try to get an image through xhr request later...
person.photo = "http://img.blogduwebdesign.com/benjamin-sanchez/737/AngularJS.jpg";
};
Is there an easier / cleaner way to do the same ?
I also created a jsFiddle : http://jsfiddle.net/V4Mss/
Thanks a lot for your feedback !
t00f
Your last example seems fine but here is another option that keeps the view a little cleaner and doesn't cause the double $digest. Remove the initialization function from each element and use the function as a getter.
HTML
<img ng-src="{{person.photo}}" />
JavaScript
myapp.controller('controller', function ($scope) {
$scope.count = 0;
$scope.get_photo = function (person) {
return "http://img.blogduwebdesign.com/benjamin-sanchez/737/AngularJS.jpg";
};
$scope.persons = [{firstname:"toto", lastname:"TOTO", photo:$scope.get_photo()},
{firstname:"tata", lastname:"TATA", photo:$scope.get_photo()},
{firstname:"titi", lastname:"TITI", photo:$scope.get_photo()}];
});
Here is a fiddle

Resources