Prevent Firebase $firebaseArray auto update - angularjs

I am working on a News Feed that is similar to Facebook News Feed. I am implementing it in the following sequence:
When app is started, get everything, but only push two item to show.
The user can scroll down to see more and I will add more to the list.
If there are any new items, the user needs to pull to refresh to add the new ones.
The only problem I have right now is that each time an item is added, $firebaseArray automatically adds the new item to my array that I do not want snyc changes (I want to query once, get a set list). I was wondering if anyone would know how to prevent the auto update?

Look into .once this will allow you to get the data just once: https://firebase.google.com/docs/reference/js/firebase.database.Query#once

Instead of binding directly your $firebaseArray to the view, clone it to a scope (or controller) property that will be bound to the view. Factorize this process in a function you can call when the user pull-reloads so the the $firebaseArray is re-created.
A more appropriate approach would be to use Firebase's http api, with the angular $http service.
Edit: to clone the array to a scope var, try the following:
var allEvents = $firebaseArray(queryOfeverything);
allEvents.$loaded()
.then(function(events){
$scope.allEvents = angular.map(events, function(event) {
return event; // you may want to replace this line - I am not very familiar with firebase.
})
});

Related

AngularJS - HTML binding not working properly

In my angular app, there are two pages (list & checkout). In the list page the user could search for an item and the searched item will be displayed and then the user can select the item and continue to checkout.
From the checkout page the user could return back to list page, and at that time all the items in the list page should be same as how it was left before.
For implementing this feature, my code is
on moving from list page to checkout page, all the scope data are stored in a service
returnsService.setScopeData($scope);
And on returning back from checkout page to list page, this saved data are retrieved from service and assigned to scope variables.
var restoreScopeData = returnsService.getScopeData();
if (restoreScopeData) {
for (var key in restoreScopeData) {
if (key.charAt(0) != '$') {
$scope[key] = restoreScopeData[key];
}
}
}
This works fine to an extend, and I can see the list page same as how I left it.
But the problem is, now I'm not able to search for new item in the list page.
When ever a search happens, the items are populated to $scope.listSearch and they are displayed in html {{listSearch}}.
In the error case also,
I can see the new search data getting assigned to the $scope.listSearch, but the HTML binding is not happening.
I tried calling $scope.$apply() after the search assigning, but still not working.
Storing complete scope isn't good idea. You can just store the vars you need. Also, you can use localStorage for this.
As I understood, making new call is not an option, so you can try use $timeout.
$timeout(function() {
$scope.listSearch = myValue;
});
Instead of doing this, you may for localStorage or sessionStorage as suggsted by John.
You may check below link for example
https://www.codeproject.com/Articles/1015515/Working-With-Client-Side-Local-Storage

Angular - How can I clear factory variables when the view changes?

I'm fairly new to angular, so bear with me. :-)
I have a list of contacts in one view. I put together a service with some setter and getter functions to hold the contact ID. When the user clicks a contact on the list view, it sets the ID in the service and moves to the edit form view. This is working well, but when I'm done editing and click to go back to the list view I want to clear the variables in the service. How would I do that?
I found one other answer on this topic, but I think it's using the built in angular router instead of ui-router.
Angular updating and clearing factory variables
Also, wouldn't the method in that answer also clear the variables when the user moved from the list to the edit form in the first place?
Thanks!
If it's a route change you can use $locationChangeStart, see $location
For example in your edit controller, register for the event on route change:
var onloc = $scope.$on('$locationChangeStart', function (event, newUrl, oldUrl) {
myService.cleanUp(whatever);
onloc();
});

How to reload the ionic view?

I have created a sidemenu based app, in that after login I am displaying a number of tasks. If I click on the task it will redirect to the task details page, in that page I can update the tasks.
So after updating a task I need to go back to the previous task list page. I am using $ionicHistory.goBack(); to go back.
My problem is after come back, I need to refresh the task list i.e. updated task should not be there in the task list. How can I refresh/reload the task list?
If you bind your task to a tasks array, which will be used in the task list page, it should be automatically updated.
But the question is about not displaying, newly added tasks (still my previous suggestion should work) if not, performance reasons ionic views are cached, So when you come back to the previous view it doesn't go through the normal loading cycle. But you 2 options
1 - disable the caching by using <ion-view cache-view="false" view-title="My Title!"> in your ion-view, but this is not a very elegant solution. read more
2 - use ionRefresher (my preferred). read more here
https://github.com/angular-ui/ui-router/issues/582
according to #hpawe01 "If you are using the current ionicframework (ionic: v1.0.0-beta.14, angularjs: v1.3.6, angular-ui-router: v0.2.13), the problem with the not-reloading-controller could be caused by the new caching-system of ionic:
Note that because we are caching these views, we aren’t destroying scopes. Instead, scopes are being disconnected from the watch cycle. Because scopes are not being destroyed and recreated,controllers are not loading again on a subsequent viewing.
There are several ways to disable caching. To disable it only for a single state, just add cache: false to the state definition.
This fixed the problem for me (after hours of reading, trying, frustration).
For all others not using ionicframework and still facing this problem: good luck!"
Hope this helps.
You can also listen to ionic events such as $ionicView.enter on $scope and trigger the code that refreshes the list if you haven't bound your list as #sameera207 suggested.
EG:
// List.controller.js
angular.module('app')
.controller('ListController', ['$scope', function($scope) {
// See http://ionicframework.com/docs/api/directive/ionView/ for full events list
$scope.$on('$ionicView.enter', function() {
_someCodeThatFetchesTasks()
.then(function(tasks) {
$scope.tasks = tasks;
});
});
});
Bear in mind that it's not the most proper way (if proper at all) and if you do this you certainly have a design flaw. Instead you should share the same data array via a factory or a service for example.
For your task you can also use ion-nav-view.
It is well documented. And if you are using now Ionic 2 beta you can use some of the view lifecyle hooks like onPageWillLeave() or onPageWillEnter(). I just faced the same problem and defined a refresh() function, but the user had to click on a button to actually update the view. But then I found:
https://webcake.co/page-lifecycle-hooks-in-ionic-2/
You just have to import the Page and NavController module and also define it in the constructor. The you can use for example onPageWillEnter(), which will always invoke when you go again to a view:
onPageWillEnter() {
// Do whatever you want here the following code is just to show you an example. I needed it to refresh the sqlite database
this.storage.query("SELECT * FROM archivedInserates").then((data) = > {
this.archivedInserates =[];
if (data.res.rows.length > 0) {
for (var i = 0; i < data.res.rows.length; i++) {
this.archivedInserates.push({userName:data.res.rows.item(i).userName, email:
data.res.rows.item(i).email});
}
}
},(error) =>{
console.log("ERROR -> " + JSON.stringify(error.err));
});
}
With ionic beta 8 the lifecylcle events changed their names. Check out the official ionic blog for the full list of the lifecycle events.
if you are building data driven app then make sure use $ionicConfigProvider.views.maxCache(0);in your app.config so that each review can refresh for more details read this http://ionicframework.com/docs/api/provider/$ionicConfigProvider/

AngularJS $resource management

I am trying to find a clean way to manage my $resource models in my application. I have some RESTful endpoints for a template model:
GET /api/templates/ //query all template
GET /api/template/:id // get single template by id
PUT /api/template/ // create a new template
PATCH /api/template/:id // update a template
DELETE /api/template/:id // delete a template
var TemplateResource = $resource('/api/templates/:templateId', {templateId:'#id'}, {
'create':{method:'PUT'}
})
I can simply run
var templates = TemplateResource.query(function(){
console.log(templates) // an array of template models
}
Once I have the list in memory, I use an Angular service to keep the list in state and consecutive calls just return the list rather then making the call again.
Now my question is regarding how to manage a single template. If the user goes to the "Edit Template" view, then saves the template I run template.$save() to run a POST on the template. The problem is that this template is seperate from the list that was pulled in from the query, so the list doesn't get updated in the UI.
Should I stem all my single template requests from my list of templates? (meaning I never actually call GET /api/template/:id, instead I just always find the template in the list)
OR
Should I just continue to run individual calls on the template, and when the POST request comes back, I just "update" the current list of templates with the updated model.
Let me know if I should provide more info about something

Angular CRUD, update view when backend/database changes ($resource and REST)

I am currently making an application in angular which does this:
(On page load) Make an api call in angular controller (to symfony2 end point) to get: items.
$scope.items = ItemsService.query(function(data){
$scope.loading = false;
}, function(err){
$scope.loading = false;
});
items is an array containing many item objects.
Each item contains parameters e.g. item.param1 item.param2.
I have built it in a similar way to this tutorial:
http://www.sitepoint.com/creating-crud-app-minutes-angulars-resource/
i.e. The angular controller calls a service which calls the (symfony2) backend api endpoint.
The endpoint passes back items which is gets from a database. Items are then put into the view using ng-repeat (item in items).
This all works fine.
Now, I have a button (in the ng-repeat) which effectively causes a PUT request to be made to (another symfony2 endpoint), thus updating item.param1in the database. This also happens in the tutorial I linked to.
The problem is that (in my application and in the tutorial) I have to again make an api call which updates ALL the items, in order to see the change.
I want to just update the data in the view (immediately) for one object without having to fetch them all again.
i.e. something like:
$scope.items[4] = Items.get({id: item.id}, function(){});
Except the application array key isn't known so I cant do that.
(so something like: $scope.items.findTheOriginalItem(item) = Items.get({id: item.id}, function(){});.
Another possible solution (which seems like it may be the best?). I have looked here:
http://teropa.info/blog/2014/01/26/the-three-watch-depths-of-angularjs.html
And tried doing the equality $watch: $scope.$watch(…, …, true);. Thus using watch to see when the item sub-array is updated. This doesn't seem to update the data in the view though (even though it is updating in the database).
Any advice on the best way of doing this (and how to do it) would be great! Thanks!
Essentially the button click should use ng-click to execute a function and pass the item to that function. Example:
...ng-repeat="item in items"...
<button type="button" ng-click="updateItem(item)">Update</button
...
Then in the function you have the exact item that you want to update. If you are using $resources, it would be something like:
$scope.updateItem = function(item) { item.$update(...); };
Unless I didn't understand you

Resources