Angular JS ng-repeat element does not update - javascript

I have to display a list of products and be able to click on them to get more informations about them.
My list of products is stored in a service named: "productsServices"
I got an html page who display all my products and an other who display details for 1 product. Each html page have their own controller.
When I update a product in my detail page, the changement is done in my productsServices but are not validated in my global product view.
(function ()
{
angular.module('app').service('productsServices', ['$http', '$q', ProductsServices])
that = this
that.products = /*arrayOfData*/;
that.getProducts = function () {
return that.products;
}
})();
(function ()
{
angular.module('app').controller('ProductsController', ['$http', '$q', 'productsServices', ProductsController])
that = this
that.products = productsServices.getProducts;
that.showDetail = function (item) {
$state.go('menu.product', { myParam: item });
}
})();
<!--Global HTML page-->
<ion-content id="content" class="has-header has-subheader" delegate-handle="myScroll">
<ion-list>
<ion-item ng-repeat="product in that.products() track by product.ProductId" href="#" ng-click="that.showDetail({{product}})">
<div class="innerProd">
<img id="productPicture" name="productPicture" ng-src='data:image/png;base64,{{product.ThumbnailPhoto}}'></div>
<div class= "innerProd">
<p>{{product.Name}}</p>
<p>{{product.Price}}$</p>
<ion-option-button class="button button-assertive"
ng-click="doDelete({{product}})">
Supprimer
</ion-option-button>
</div>
</ion-item>
</ion-list>
<ion-infinite-scroll ng-if="moreDataCanBeLoaded()" icon="ion-loading-c" on-infinite="loadMoreData()" distance="100%">
</ion-infinite-scroll>
</ion-content>
So when I check the product sended in the "that.showDetail" method, it's the old product who is sended even if the product have been updated in the services.
I'm not english so sorry for language mistakes in my sentence ^^'
Thank in advance for your help ^^'

Ok I've find the ansewer to my question, I've replace the parameter that I'm sending to my "that.showDetail" function. I'm no more sending the object directly, but the index of my item.
<ion-item ng-repeat="product in that.products() track by product.ProductId" href="#" ng-click="that.showDetail({{$index}})">
I guess that angular doesn't update injected in a ng-click call ^^'
Thank you for your time guys

Related

Create a favorite list in AngularJS

I want to create a favorite list in my application based on user selection. In my app, I use a long JSON file with a bunch of text which is loaded with $http.get().
This is code for displaying content in my view.
<ion-view>
<ion-nav-title></ion-nav-title>
<ion-content>
<div class="card" ng-repeat="list in items | filter: { id: whichid }">
<div class="item item-text-wrap"
ng-repeat="item in list.content | filter: { id2: whichid2 }"
ng-bind-html="item.description.join('')">
<h3>{{ item.name }}</h3>
<p>{{ item.description }}</p>
</div>
</div>
</ion-content>
The basic idea for creating a favorite list is to save displayed text in the array. After that, I can easily print that array in a template for the favorite list.
So the problem is how I can save text/data form expression ({{ item.name }}, {{ item.description }}) to the array? Or if anyone has some other idea for making that favorite list.
Pass the item details to a function defined in your controller using ng-click and push it into an array as shown below :
<ion-view>
<ion-nav-title></ion-nav-title>
<ion-content>
<div class="card" ng-repeat="list in items | filter: { id: whichid }">
<div class="item item-text-wrap" ng-click="favouriteThis(item)"
ng-repeat="item in list.content | filter: { id2: whichid2 }"
ng-bind-html="item.description.join('')">
<h3>{{ item.name }}</h3>
<p>{{ item.description }}</p>
</div>
</div>
</ion-content>
In your controller :
Write the "favouriteThis" function to push the favourited item every time the user clicks on it :
$scope.favouriteList = [];
$scope.favouriteThis = function (item) {
$scope.favouriteList.push(item); // make sure to check for duplicates before pushing the item, the logic for which i've not included here.
}
As you have all the favourited item details in the "$scope.favouriteList", you can use that information in your favourite list directly. To make it more accurate, while checking for duplicates you can also record the number of times user interacted with a particular item using which you can show the most interacted item on the top of the list.
Hope this helps :)
I would suggest creating a service/controller for this approach since you are making http calls which return JSON objects (use a service, as well as a controller). In the service have your functions such as getFavorites, addToFavorites, deleteFromFavorites etc. These functions will http GET/POST/UPDATE on your favorites list. Then you will want to return the JSON object to a controller. In the controller you'll have control over the scope and set scope variables to display the data in your app.
Here is a basic example:
Service
//****************
//Favorite Factory
//****************
.factory('favoriteFactory', function ($http) {
var favFac = {};
var favorites = [];
favFac.getFavorites = function (userId) {
//$http.get() call to get specific user's favs
};
favFac.addToFavorites = function (name, description) {
//$http.post() call to post to a users favs
};
favFac.deleteFromFavorites = function(userId, itemId) {
//$http.update() call to delete item from users favs
}
return favFac;
});
Controller
//Favorite Controller
.controller('FavoritesCtrl', ['$scope', '$stateParams', 'favoriteFactory', function ($scope, $stateParams, favoriteFactory) {
//Route current user Id to controller. Pass to service to look up their favorites in db
var userId = $stateParams.id;
$scope.favorites = favoriteFactory.getFavorites(userId);
$scope.addToFavorites = function(name, description){
favoriteFactory.addToFavorites(name, description);
}
}])
HTML
<ion-view view-title="Favorites Page" ng-controller="FavoritesCtrl">
<ion-content>
<ion-item collection-repeat="favorite in favorites">
<h3>{{ favorite.name }}</h3>
<p>{{ favorite.description }}</p>
<button type="button" ng-click="addToFavorites(favorite.name, favorite.description)">Add</button>
</ion-item>
</ion-content>

AngularJS $scope variable will not display in ionic view using GET request

I am having an issue displaying response data, returned from my factory,inside an ionic view page. I believe the issue has something to do with the way I am handling the promise, but I cannot pinpoint why. So to start the roadmap to my problem, here is my:
Factory
.factory('profileFactory', function ($http, $q) {
var config = {
headers: {
'MyKey': 'myvalue'
}
};
this.getEmployee = function (userId) {
return $http.get('http://someurlpathtogoto' + userId + 'etc', config).then(function (response) {
console.log(response.data)
return response.data;
})
}
return this;
})
The above code returns the JSON object I need for my controller so:
Controller
.controller('EmployeeCtrl', ['$scope', 'profileFactory', function ($scope, profileFactory) {
//Set back to false
$scope.profileLoaded = true;
$scope.serviceUnavailable = false;
$scope.setId = function (userId) {
profileFactory.getEmployee(userId).then(function(arrItems){
$scope.employee = arrItems;
$scope.firstName = $scope.employee.record[0].First_Name;
$scope.lastName = $scope.employee.record[0].Last_Name;
};
}])
Now when my page displays I want it to look like such:
Ionic View (Profile)
<ion-view view-title="Profile" ng-controller="EmployeeCtrl" hide-nav-bar="true">
<ion-pane>
<!-- TODO: BACK BUTTON, NO TITLE -->
<ion-header-bar class="bar-stable">
<h1 class="title">Ionic Blank Starter</h1>
</ion-header-bar>
<ion-content>
<div ng-show="serviceUnavailable">
Directory service unavailable
</div>
<div ng-show="profileLoaded">
<br />
<center><img class="focus-img-circle" ng-src="default.png" /></center>
<center><b>{{firstName}} {{lastName}}</b></center>
</div>
</ion-content>
</ion-pane>
<ion-view>
All of this is invoked whenever a user presses on an arrow button in the app which should take them to their profile page to view some info. The following code appears in the previous view.
Ionic View (Search Results)
<ion-item class="item item-avatar item-button-right" ng-repeat="user in results" ng-controller="EmployeeCtrl">
<img ng-src="data:image/png;base64,{{user.pic}}">
<strong>{{user.first_name}} {{user.last_name}}</strong>
<div class="buttons" style="padding:20px;">
<button type="button" class="button button-icon ion-ios-telephone-outline customSearchIcon" ng-click=""></button>
<a class="button button-icon ion-ios-arrow-right customSearchIcon" ng-click="setId(user.id)" href="#/tab/search/profile"></a>
<button type="button" class="button button-icon ion-ios-heart-outline customSearchIcon" ng-click="addFavorite(user.id, user.first_name, user.last_name, user.pic)"></button>
</div>
</ion-item>
So essentially a user clicks on a persons tab, takes them to that profile where my factory is used to make a RESTful call to return a JSON object containing data about that user. Except nothing is being displayed in the Ionic View. If I hard code a userId in the controller and take away the function setId() it works but that obviously isn't an option. Does anyone see anything specifically that I am doing wrong? Been stuck on this for hours any help would be great.
I left a lot of code out to get my point across.
EDIT
The two views you see are different ionic templates. So using ng-controller="EmployeeCtrl is not happening twice in the same view.
The mistake is, on arrow click, you call the service and store the data to scope variable and then navigates to second view. The second view though uses the same controller as the first view, a new controller is being instantiated with empty scope - and hence your view is empty.
Instead of ng-click in <a> tag, modify your profile route to pass the userid as well - tab/search/profile/:userid and in anchor tag have ng-href= "#/tab/search/profile/{{user.id})" and in your profile controller get the userid from query string ($location.search().userid) and make the Ajax call.

add 1 to value after submission to databse with angular

I'm working on a project where user can like comment made by users. and what i want to achieve is when a user likes a comment on a page by default + 1 should be added to the total comments made. Below is my script my it doesn't work
.controller('feedsctrl',['$scope','$http',function($scope,$http){
$http.get('http://localhost/vivalooks/app_ion/like.php').success(function(data){
//$scope.feeds = console.log(data) ;
$scope.feeds = data;
$scope.lovepic = function() {
event.preventDefault();
$http.post("http://localhost/vivalooks/app_ion/scripts/comment.php",
{
'u_pic_id': $scope.u_pic_id,
'pic': $scope.pic
}
).success(function(data,status,headers,config){
console.log(data)
$scope.comment_total=$scope.comment_total+1;
});
}
});
}])
HTML
<ion-content>
<div ng-controller="feedsctrl" class="list card has-subheader" ng-repeat="item in feeds">
{{item.comment_total}} Comments
</ion-content>
Issue with your code is that you are trying to update the $scope.data[item].comments with $scope.comments. These both are different variable in angular controller scope. you should perform the addition in the same scope variable to get it reflected on the view. You can achieve this by slight modification in your code
html
<ion-content>
<div ng-controller="feedsctrl" class="list card has-subheader" ng- repeat="item in feeds trach by $index">
<img src="item.src" ng-click="lovepic($index)">
{{item.comment_total}} Comments
</div>
</ion-content>
in the controller.
$scope.lovepic=function(index) {
event.preventDefault();
$http.post("http://localhost/vivalooks/app_ion/scripts/comment.php",
{'u_pic_id':$scope.feeds[index].u_pic_id,'pic':$scope.feeds[index].pic})
.then(function(data,status,headers,config){
$scope.feeds[index].comment_total == undefined ? 1 : $scope.feeds[index].comment_total +1;
});
}

Angular Display lists from Firebase

My data in Firebase looks like this...
evalu8er
situations
-K6rM12D-0nt4fJH_QcA
situation: "Test"
-K6rPoHiUl2N2JOSWXww
situation: "Test2"
-K6rPqbkBHJ-K8znVzay
situation: "Test3"
I have inserted the data from an HTML page via a form like this...
<div class="form-group">
<label for="situation">Add a situation</label>
<input type="text" class="form-control" id="situation" placeholder="Situation" ng-model="situation">
</div>
<button type="submit" class="btn btn-default pull-right" ng-click="add_situation()"><i class="fa fa-cog fa-spin" ng-show="loading"></i> Add </button>
</form>
The above form is calling the controller...
app.controller("situations", ["$scope", function ($scope) {
$scope.add_situation = function () {
var situation = $scope.situation;
var ref = new Firebase("https://evalu8er.firebaseio.com/situations");
ref.push().set({
situation: situation
});
};
}
]);
Now I want to get each of the situations back to the page, and this where it all goes wrong for me.
Inside the same controller as above I'm adding this....
var ref = new Firebase("https://evalu8er.firebaseio.com/user/situations/");
ref.on("value", function(snapshot) {
$scope.display_situatoins = snapshot.val();
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
And on the HTML page I have added
<li data-ng-repeat="x in display_situatoins">
{{ x }}
</li>
When the page loads it DOES NOT show me the data until I enter something in the form field,
Question 1/3)
How do I get the data to show on page load?
When it does load it looks like this...
{"situation":"Test"}
{"situation":"Test2"}
{"situation":"Test3"}
And what I want is just to show a list of the situations like this..
Test
Test2
Test3
Question 2/3)
How do I just show the situation values as above?
And when I do add a new item it gets listed at the bottom, how do I order the list with the new items at the top?
Question 3/3)
How do I order the list so the new items appear first?
Use AngularFire for synchronized collections.
angular.module('app', ['firebase'])
.constant('FirebaseUrl', '<my-firebase-app>')
.service('rootRef', ['FirebaseUrl', Firebase])
.controller('MyCtrl', MyController);
function MyCtrl($scope, rootRef, $firebaseArray) {
$scope.situations = $firebaseArray(rootRef.child('situations');
}
Then in your template for MyCtrl, you can do an ng-repeat on the situations array.
<li ng-repeat="situation in situations">
{{ situation.situation }}
</li>
The {{ situation.situation }} part looks awkward because of the naming. If you change the property situation to something like text or title it would look like:
<li ng-repeat="situation in situations">
{{ situation.title }}
</li>

adding array elements to another array

I have a very big list which is an array named leagues, I need to allow the user to take the elements on that array(list) , and choose those as favorites by clicking a button
$scope.favoriteLeagues = [];
$scope.favoriteLeague = function(league) {
$scope.favoriteLeagues.push(league);
}
so I want to know what am I doing wrong ? the function sometimes allows me to add one as favorite, but once I click on the second one, I got a message of something undefined, and also, the binding is not working, I am unable to see the {{favoriteLeagues.name}} printed.
UPDATED AS REQUESTED
<div>
<strong>Favorites</strong>
{{favoriteLeagues.name}}
</div>
<ion-option-button class="button-light icon ion-star"
on-tap="favoriteLeague(league)">
</ion-option-button>
<div ng-repeat="sport in sportsFilter = (sports | filter:query)">
<strong>{{sport.name}}</strong>
</div>
<ion-item ng-repeat="league in sport.leagues">
<div>{{league.name}}</div>
</ion-item>
</ion-list>
here the controller:
.controller('SportsController', function($scope, $state,
AuthFactory, SportsFactory) {
$scope.favoriteLeagues = [];
$scope.sports = [];
AuthFactory.getCustomer().then(function(customer) {
$scope.customer = customer;
SportsFactory.getSportsWithLeagues(customer).then(function(sports) {
if (sports.length) {
$scope.sports = sports;
}
$scope.isSportShown = function(sport) {
return $scope.shownSport === sport;
};
$scope.favoriteLeague = function(league) {
$scope.favoriteLeagues.push(league);
}
};
});
You haven't pasted the full html, but it should look something like this:
<!-- Use ng-app to auto-bootstrap an AngularJS application-->
<!-- Use ng-controller to attach your view with your SportsController controller -->
<ion-list>
<div>
<strong>Favorites</strong>
<!-- Looping through all the favourite leagues-->
<div ng-repeat="favouriteL in favoriteLeagues">
{{favouriteL.name}}
</div>
</div>
<!-- Looping through all the sports -->
<div ng-repeat="sport in sportsFilter = (sports | filter:query)">
<!-- Bind the sport name -->
<strong>{{sport.name}}</strong>
<!-- Looping through all the leagues -->
<ion-item ng-repeat="league in sport.leagues">
<!-- Display a button which on tap will call favoriteLeague function -->
<ion-option-button class="button-light icon ion-star" on-tap="favoriteLeague(league)">
</ion-option-button>
<!-- Bind the name of the league -->
<div>{{league.name}}</div>
</ion-item>
</div>
</ion-list>
Don't forget to attach the view with your controller using ng-controller.
I can't help you much with angular.js, I've never used it, but the fact that you are accidentally replacing the array with the function probably doesn't help. ng-repeat is trying to loop through favoriteLeagues but fails because that's a function! Look at the comments I put in your code.
$scope.favoriteLeague = []; // creates an array
$scope.favoriteLeague = function(league) { // replaces the array with a function!!!
$scope.favoriteLeagues.push(league); // suddenly leagues takes an S ?
}
To avoid this type of error, you should respect a naming convention for your functions. I like to use action words and verbs for functions. I only use plural forms on arrays and related functions. Here's what I'd do in your case:
$scope.favoriteLeagues = [];
$scope.addToFavoriteLeagues = function(league) {
$scope.favoriteLeagues.push(league);
}
You need to attach your controller to the html in order for the bind to work, usually at the top level parent element, e.g a div, containing the ngrepeat markup.

Categories

Resources