Angularjs: push data into array from resource query and show in ngRepeat - angularjs

there is an array data retrieved from a restful API using $resource and i fetch it using query() method. so i create a new data and i want to push the data created into the fetched array from $resource which is shown in ngRepeat directive, but when i make the push function, it doesn't push and i wouldn't like to re-query the whole data again.
controller
self.submit = function(){ //This function is called when i submit data creation
var form = self.form;
form.user_id = Global.user.id;
// hide error message if it's shown
self.data.error.show = false;
// check if submition is already on request (for some reason it submit twice)
if(!self.status.request){
self.status.request = true;
$timeout(function(){
projects.save({data: form}, function(data){ //function called from $resource
console.log(data);
self.status.request = false;
// Resolve Error
if(data.error[1])
resolveError();
// merge data to list
else{
form.id = data.id;
mergeData(form);
self.closeDialog();
}
});
}, 1000)
}
// show error message
function resolveError(){
var error = self.data.error;
error.show = true;
}
// merge form data into list data
function mergeData(data){
self.query.push(data); //this doesn't seem to work
console.log(data, self.query); //log to see if data is in array
}
}
view
<md-card ng-repeat="project in projects.query | orderBy:'id':true">
<md-toolbar>
<div class="md-toolbar-tools">
<h2>{{project.Name}}</h2>
<span flex></span>
<h3>{{project.user_id}}</h3>
</div>
</md-toolbar>
<md-card-content>
<p>{{project.Description}}</p>
</md-card-content>
<div class="md-actions" layout="row" layout-align="end center">
<md-button ng-href="#/projects/{{project.id}}">View</md-button>
</div>
</md-card>
note: the data is saved on the database, and for now the only way to see it on the list is by refreshing the page
update: projects is the alias of ProjectsController

Related

Is there any way to load individual data and display it rather loading and display all data using angularjs?

Consider I have 10 locations and I have to display each location's weather conditions. It is easy to fetch all locationids and feed it to a function to get all 10 location's data at a time and display it. But I want to load individually from server side and feed it to angular section. ie when first location data loaded then display it then second and so on.. Is that possible?
This is my angular code. This working fine. I want to change to above mentioned logic
var locations = [1,2,3,...,10];
locationService.UpdateDashBoard(locations).then(function (result) {
$scope.results.push(result.data);
});
And Html code is
<li gridster-item="widget" ng-repeat="widget in results">
<div class="text-center wrap-text">
<span ng-show="!editMode">{{ widget.name }}</span>
<label style="cursor: move" ng-show="editMode">{{ widget.name }}</label>
<div class="pull-right" ng-show="editMode && widget.Source">
Location - {{widget.location}}
temperature - {{widget.Source.temperature}}
</div>
</div>
</li>
While your locationService.UpdateDashBoard function may accept multiple ids, as you stated in your question, passing a list of ids will result in all data being returned at once. Given your requirement to load each location individually, you could simply call the service once for each id:
var locations = [1,2,3,...,10];
locations.forEach(function(location) {
locationService.UpdateDashBoard([location]).then(function (result) {
$scope.results.push(result.data);
});
});
After each call responds the location's data is pushed in the $scope.results array. This is where angular's magic kicks in...as you have bound the ng-repeat directive to your results array - the UI will automatically update after each new location is added.
It sounds like that you wanted to do a sequencing request by chaining each of the id one after another. I would recommend to use $q to do that.
var locations = [1,2,3,...,10];
// create a "start" promise
var promiseChain = $q.when(function(){});
// loop each locations
locations.forEach(function (location) {
// promisify the locationService function
var promiselink = function () {
var deferred = $q.defer();
locationService.UpdateDashBoard([location])
.then(function (result) {
$scope.results.push(result.data);
deferred.resolve()
});
return deferred.promise;
}
// promiseChain will wait until promiselink return with the promise
promiseChain = promiseChain.then(promiselink);
})
The promiseChain.then(promiselink); should do the trick since it waits for promise to be resolved from promiselink function.
If I understand this correctly, you want to get all data in one hit (results) but add them to the DOM incrementally. I'm not sure MS_AU's answer will provide the right functionality you need - it looks like it will call the server for every id, but pass the entire array and returns all data from the server every time. You'd end up with 100 items in $scope.results.
Edit: If my understanding of your question is correct you want to call the server for each id, so you should change your service method to accept one id, and iterate over the ids and call the function.
If you return the promise in a private function you can call .then() inside the forEach loop and push the result. If you don't return the $promise in the service function, you'll need to handle the .$promise in the controller.
var locations = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var updateDashboard = function(id) {
return locationService.UpdateDashBoard(id);
};
locations.forEach(function(id) {
updateDashboard(id).then(function (result) {
$scope.results.push(result.data);
});
});
And your HTML:
<li gridster-item="widget" ng-repeat="widget in results">
<!-- fade is just an ng-animate class I picked, you can choose your own or none -->
<div class="text-center wrap-text fade">
<span ng-show="!editMode">{{ widget.name }}</span>
<label style="cursor: move" ng-show="editMode">{{ widget.name }}</label>
<div class="pull-right" ng-show="editMode && widget.Source">
Location - {{widget.location}}
temperature - {{widget.Source.temperature}}
</div>
</div>
</li>

dynamically updating contents from the results of the cloud api using angular js

i am using angular js, bootstrap thumbnail and google cloud endpoints for my app.
The .html looks part looks like:
<body ng-controller="SearchController as searchCtrl">
<div class="row">
<div class="col-sm-2 col-md-2" ng-repeat="result in searchCtrl.searchResults">
<div class="thumbnail">
<img ng-src="{{result.thumbnailUrl}}">
</div>
</div>
</div>
The .js looks like below
(function(){
var app = angular.module('InstaMonitorAdmin', []);
app.controller('SearchController', function(){
this.searchResults = {};
this.searchTags = function(keyword){
//this.searchResults = results;
gapi.client.instagramApi.searchTags({'keyword':keyword}).execute(function(resp) {
if(resp && resp.hasOwnProperty('error')) {
// error
alert(resp.error.message);
}else{
var myJsonString = JSON.stringify(resp.items);
this.searchResults = myJsonString;
console.log(myJsonString);
}
});
};
});
In the console debugger it shows data for myJsonString as:
{"userName":"vikceo",
"caption":"#sandsculpture #sandcastle",
"tags":"[mountains, breathtaking, love, skyporn, minion]",
"thumbnailUrl":"https://scontent.cdninstagram.com/t51.2885-15/s150x150/e35/13108860_653673808116072_1235622514_n.jpg",
"kind":"instagramApi#resourcesItem"},
{"userName":"neetipari","caption":"My love #passion",
"tags":"[weddingcake, love, fondantcakes, foodporn]",
"thumbnailUrl":"https://scontent.cdninstagram.com/t51.2885-15/s150x150/e35/12940136_423862367814317_252510398_n.jpg",
"kind":"instagramApi#resourcesItem”}]
The issue is that the page does not render the search results returned from the google end point. I have tested that it return the results fine.
if i comment it and uncomment the top line where i am passing a hard coded array then it works fine.
Is it because it takes more time for response to come and assign to array? I thought it will continue to listen to this array. Please advise
so the problem turned out to be how i assigned the returned results. this is the final method:
app.controller('SearchController', function(){
this.searchResults = {};
this.searchTags = function(keyword){
var data = this;
data.searchResults = [];
gapi.client.instagramApi.searchTags({'keyword':keyword}).execute(function(resp) {
if(resp && resp.hasOwnProperty('error')) {
// error
alert(resp.error.message);
}else{
//successful login
console.log(resp);
data.searchResults = resp.items;
}
});
};
To have a synchronous assignment to the array , you could wait for the execution such as:
gapi.client.instagramApi.searchTags({'keyword':keyword}).execute(function(resp)).then(function(ress) {
//console.log(ress.items);
this.searchResults = ress;
});
Just add an ng-if, if you add ng-if element creates after data is come
<div ng-if="searchCtrl.searchResults.length" class="col-sm-2 col-md-2" ng-repeat="result in searchCtrl.searchResults.items">
<div class="thumbnail">
<img ng-src="{{result.thumbnailUrl}}">
</div>
</div>

Angularjs how can I reload the content

I have this code that loads the content when the page load,
Now I want to know how to reload the content by clicking the button.
Can you show me how to do it with example please?
Javascript code:
.controller('InterNewsCtrl', function($scope, NewsService) {
$scope.events = [];
$scope.getData = function() {
NewsService.getAll().then(function (response) {
$scope.events = response;
}), function (error) {
}
};
$scope.getData(); // load initial content.
})
Html code:
<ons-toolbar fixed-style>
<div class="left">
<ons-back-button>Voltar</ons-back-button>
</div>
<div class="right">
<ons-toolbar-button><ons-icon icon="ion-android-refresh"></ons-icon></ons-toolbar-button>
</div>
<div class="center">Internacional</div>
</ons-toolbar>
I think you're asking how to just retrieve new events from the backend. If that's correct, you don't need to reload the entire page.
You already have a function called getData which goes and retrieves you data via your service. Assuming your service doesn't cache the data, just call getData from your button:
<ons-toolbar-button ng-click="getData()"><ons-icon icon="ion-android-refresh"></ons-icon></ons-toolbar-button>
P.S. if you do explicitly have the cache set to true in your service, you can remove the cached data with $cacheFactory.get('$http').removeAll();.
For reloading same page in angular Js without post back
first remove that url from template cache if you call $route.reload() without removing it from $templateCache it will get it from cache and it will not get latest content
Try following code
$scope.getdata=function()
{
var currentPageTemplate = $route.current.templateUrl;
$templateCache.remove(currentPageTemplate);
$route.reload();
}
and Call it as following
<input type="button" ng-click="getdata();" value ="refresh"/>
Hope this will help
Please reffer this

Prevent ngRepeat flicker with promise in AngularJS

I have a collection of objects, say Products, which I can interact with using $resource. On an index page, I'd like to either display the collection, or, in the case the collection is empty, display a helpful message. i.e.
In Controller
$scope.products = Products.query();
In Template
<div ng-repeat="product in products">
...
</div>
<div class="alert" ng-hide="products.length">
<p>Oops, no products!</p>
</div>
This works fine, provided the user isn't staring at the spot where the ng-repeat will occur. If they are, or if there is a delay in the response from the server, they may notice a slight flicker, before the promise is resolved.
Given that, "invoking a $resource object method immediately returns an empty reference" (see here), such a flicker will always in this example. Instead, I find myself writing:
<div class="alert" ng-hide="!products.$resolved || products.length">
<p>Oops, no products!</p>
</div>
Which takes care of the flicker. However, I'm not too keen on letting my view know exactly how the products are obtained. Especially if I change this later on. Is there anything cleaner I could do? I'm aware that a fallback for ng-repeat is in the works (see here), however, just wondering if there's a cleaner solution in the meantime.
You could use the success method to set the object:
Products.query(function(data) {
$scope.products = data;
});
Or use the promise:
Products.query().$promise.then(function(data) {
$scope.products = data;
});
This way, the object doesn't become empty until you get a response.
You can get $promise out of $resource and change displayed information before/after promise is resolved.
Say you have following Products and service to get them.
/* products */
[
{ "id":1, "name":"name1" },
{ "id":2, "name":"name2" },
...
]
/***/
app.factory('Products', function ($resource) {
return $resource('products.json');
});
Then in your controller assign data only after promise is resolved.
app.controller('MainCtrl', function ($scope, Products) {
$scope.initialize = function () {
$scope.products = null;
Products.query().$promise.then(function (data) {
$scope.products = data;
});
};
$scope.initialize();
});
In your HTML template you can take care of the cases like a) not yet resolved b) resolved c) resolved but no data
<body ng-controller="MainCtrl">
<div ng-show="!products">
Getting data... please wait
</div>
<div ng-show="products && products.length === 0">
Oh noes!1 :( No products
</div>
<div ng-show="products">
<span ng-repeat="product in products">
{{ product | json }} <br>
</span>
</div>
<div>
<button type="button" ng-click="initialize()">Refresh</button>
</div>
</body>
Related plunker here http://plnkr.co/edit/Ggzyz9

How to show value on ng-click event?

I am bit new to AngularJs and looking for help on some basic concepts.
Basically the following code correctly shows data returned from request API.
Request.cshtml
<div data-ng-controller="PostsController">
<strong class="error">{{ error }}</strong>
<strong data-ng-show="loading">loading..</strong>
<div data-ng-repeat="request in posts | orderBy: 'Id':true">
<strong>ID: {{ request.Id }}</strong>
<strong>Contact No: {{ request.ContactNumber }}</strong>
</div>
</div>
now i am further looking to add button in view and when user click on in, the contact number should be displayed.
i have written following html/angular view code.
show number
I need help in writing the corresponding "ShowNumber()" function in PostsController.js file.
But i am confused how to send single value instead of lists. Any help on it please?
here is my current PostsController.js code
function PostsController($scope, $http) {
$scope.loading = true;
$scope.editMode = false;
$http.get('/api/request').success(function (data) {
$scope.posts = data;
$scope.loading = false;
})
.error(function () {
$scope.error = "An Error has occured while loading posts!";
$scope.loading = false;
});
}
The function:
$scope.ShowNumber=function(value){
//Your logic
}
HTML
<input type="button" value="Show" ng-click="ShowNumber(request.Id)" />
You can send any value in the function.
Also you can send a index of list:
ng-click="ShowNumber($index)"

Resources