I am wondering how AngularJS 'saves' its data/model. Does it actually save it or.. how does it work?
We are using different methods to retrieve JSON data. In other frameworks like jQuery we had to think about how to store data locally, i.e. when we want to provide a sorting possibility. In Angular this seems different, it seems to do all that for us out of the box.
Is it that Angular displays everything how it is supposed to be and looks at changes, reads in the displayed data in and then displays it differently or does it use a local storage to save the raw json.. and work from there? (This would limit the amount of data we can feed)
Here is a simple code-example:
$http.get("url-to-json")
.success(function(returnedData) {
$scope.search_result = returnedData['search_result'];
})
From there I can just use:
<div ng-repeat='result in search_results | sortResult:"price":sorted' id="res_<% result.id %>" class="result">
Product: <% result.name %>
</div>
I am riddled how Angular still knows the data and doesn't have to load it again from the external source.
Do you know?
There is a lot more that goes into it, but essentially its all stored in local memory. Angular creates an object of all your scope properties. When you do data binding in angular you are registering an event listener and when that event is called angular loops through this object detecting if something has changed, and if so updates the object accordingly. Each time an update occurs it returns to the loop to check if anything else has been updated. This is what is referred to as the $digestLoop.
SOURCE
The ng-book
Related
I am pretty new with angular js. My use case is We have a parent page say parentPage.html where we have a link. On click of this link in parentPage I want to send a server hit to a spring controller, which should return us a json response. I want to paste this response in the new window against the childpage.html. How can we achieve this by angular js?
parentPage.html:
Show New Customer
ajax response on click of above link:
{
customerName:'Adam',
address:'XYZ',
}
childPage.html(we have to iterate over the above key value pairs such that our result should be painted in the following way:-)
<table>
<tr>
<td>customerName:</td>
<td>Adam:</td>
</tr>
<tr>
<td>address:</td>
<td>XYZ:</td>
</tr>
</table>
On google I found enough stuff about the means by which we have to bring things within the scope. My only confusion in this usecase is, since we have to open a new window after sending the http get request(which is being sent from the parentPage.html), the response of which is to be painted in an absolutely new window(which is childPage.html), so isn't this scope going to get lost somewhere since we are not dealing with SPA thing here? Can we achieve this by angular in any possible way?
Since angular is meant to work off a one page application and retain the state of most javascript throughout the duration of the application being ran, you really have two option.
The first is to take that JSON response and store it in local storage.
window.localStorage.setItem('key', value);
By doing this, you will be able to pull the value back out at any point by use of the following
value = window.localStorage.getItem('key');
In most cases, you would want to stringify() the JSON before parsing it all out again.
This is one implementation which would definitely work out for you.
Another option would be to make use of ng-model, models are used to store and manipulate data in angularjs, By passing around these values back to your controllers you will be able to easily hold and interact with the state of these variables.
I have this code for my table :
##
<tr ng-repeat="elt in tabDemandes">
<td>{{elt.id}}</td>
<td>{{elt.name}}</td>
<portlet:renderURL var="maj">
<portlet:param name="action" value="maj"/>
<portlet:param name="idD" value="elt.id"/>
</portlet:renderURL>
</tr>
##
I want recover a value of my param "idD" in my controller but it take elt.id as a value of a param and he give me error
can someone help me ?
To have access to the idD in your controller just set a $scope that can hold it. Angularjs is built with 2-way data-binding in mind so really what this lets you do is make changes in the view that will go to the controller as well as changes in the controller being pushed out to the view.
In your case just make sure you are storing the idD as an ng-modle that links back to a scope you declared in the controller. Once you have that linked correctly you can get the idD in your controller no problem.
Obviously, the difference is that the JSTL taglib (<portlet:renderUR>L) runs on the server, while AngularJS and the ng-repeat runs on the client. At the moment AngularJS is looping over your content, the URL has already been rendered.
For more information about the differences of server- and clientside, look at this answer: What is the difference between client-side and server-side programming?
What we did was quite simple, we attached the URLs to our model (in your case tabDemandes). This is an example we used for creating an action URL with the ID as a parameter:
PortletURL detailURL = response.createActionURL();
detailURL.setParameter(ActionRequest.ACTION_NAME, "detailTask");
detailURL.setParameter("id", Long.toString(task.getId());
task.setDetailURL(detailURL.toString());
In this case we were using a list of tasks, and we used this action URL to open a detailed page of the task, so we had to pass the ID to the action URL. In stead of using the JSTL taglib we used the Java API.
In your case you'll probably need to use response.createRenderURL().
I have a set of files in a server which I am looping though and constructing a JSOn and saving it as a separate file. I am using python for this. Works quite well. Now the scope is the number of files in the directory will increase/ change throughout the day..and I am running the script every 10 min to rewrite the json...the file name stays same and i am calling it in a single page html document using angular.js..Again fairly simple...But now I am having problem when the JSON is changing I am not seeing any change on the page unless I reload the page. Could I do something about this?
With angular I am using
$http('something.json').success(callback function with some argument data)
and in the markup something like
<ul>
<li ng-repeat="x in data">{{x.id}}</li>
</ul>
Your call to $http is one-time operation which happens after page load like this:
$http('something.json').success(function(data){
$scope.data = data;
});
angular is kickstarted
ng-controller containing $http request is evaluated and request for 'something.json' is sent
...
when your json arrives, your success function is called with data from json
view (html template) is updated with new data
Angular keeps your model (eg $scope.data) and UI (expressions in template) up to date, but it doesn't update external resources.
If you want to periodically poll for changes in 'something.json'
you can use $timeout service as suggested in JaKXz's comment.
I'm new to Firebase and AngularJS (and AngularFire), but am managing to work most things out... however this one's stumping me.
Situation:
I've got a server and a separate frontend. The frontend has NO WRITE PERMISSIONS for Firebase - it can only read it's own data (using a token provided by the server). The server has an API which the frontend utilises to make updates.
For the frontend to request an update to a particular item in a list, it needs to provide that item's Firebase ID to the server (along with whatever other information the API needs). The server will first verify that ID and then use it to update the correct Firebase data.
I've got AngularFire doing a three-way data binding for these actions, which is awesome!
Problem:
Lets say my Firebase structure is as follows:
actions: {
-JFeuuEIFDh: { // Firebase IDs for arrays
label: "One",
.
.
.
},
-JfuDu2JC81: {
"label": "Two",
.
.
.
}
I have the following HTML:
<div ng-controller"SuperController">
<ul>
<!-- key is the Firebase ID for the action, which is
required for my server to know which object to update -->
<li ng-repeat="(key, action) in actions">
<a ng-click="doAction(key, action)">action.label</a>
<!-- **Loading IS NOT and SHOULD NOT be stored in Firebase,**
it's simply a local state which AngularJS should manage -->
<p ng-hide="!action.loading">Loading...</p>
</li>
</ul>
</div>
doAction looks something like this:
$scope.doAction = function(key, item) {
$scope.actions[key].loading = true;
var onComplete = function () {
$scope.actions[key].loading = false;
}
// Calls to the server, etc...
.
.
.
}
I'm using $scope.actions[key].loading to provide a local state so the "Loading..." paragraph will appear when the user initiates doAction, and disappear when the doAction logic completes.
However, because AngularFire has set up a three-way data binding, it tries to save that change to the database, which fails because the client does not have permission to write!
I don't want it to save loading to the database! It's there simply to update that paragraph's ng-hide - it shouldn't be persistent and there's no way this would justify providing write permission to the client.
So what am I supposed to do? I can't think of any way to update the scope without firing off the three-way binding... Am I thinking of this the wrong way?
EDIT
Nested deep in the AngularJS documentation, under $FirebaseObject.$bindTo, was this:
use a variable prefixed with _, which will not be saved to the server, but will trigger $watch().
However when I used $scope.actions[key]._loading instead, the same problem still occurred. There was no apparent difference.
I couldn't find a clean solution to the problem.
use a variable prefixed with _, which will not be saved to the server, but will trigger $watch().
This wasn't actually implemented in code. I was considering submitting an implementation myself but it wasn't as simple as I hoped. Even after toJSON stopped returning _'d variables, it still tried to save the (unchanged) JSON to Firebase, so you'd have to fix it earlier somehow... I didn't go there.
To solve the problem I used AngularFire's $asArray instead of $asObject. The array is READ ONLY. Firebase won't try to sync any changes unless you call special functions. In my case, this works, however in other cases it might not be sufficient.
I had to change a bit my templating to work with an array instead of an object since a numerical key was now being provided instead of the actual key being used in Firebase. I converted the numerical key to the proper one with: actions.$keyAt(parseInt(key)).
It was a mess.. but it'll get me through for now.
I am having same issue. but this seems to fix it.
https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebaseobject-bindtoscope-varname
If $destroy() is emitted by scope (this happens when a controller is > destroyed), then this object is automatically unbound from scope. It can > also be manually unbound using the unbind() method, which is passed into ? > the promise callback.
//Setup synced array as usual
$scope.syncedArray = $firebaseArray(ref);
//call unbind on the variable
$scope.syncedArray.unbind();
//reorder, filter and maniuplate arrays as usual and when done call .bind() on it.
I'm using angular translate for i18n.
The particular feature I'm working on is updating the status of a book. In the service callback, if successful, I am updating my book status from, say, Open to Closed. If I view the scope (using Batarang), I can see my DOM element as such:
<span translate="Closed" class="ng-scope">Open</span>
As you can see, the translate value is being updated, but the translation itself isn't occurring on its own. I've read the docs and understand this is expected behavior. What I want to know, though, is how should I be refreshing the translated value?
Presently, I'm injecting the $translate service and executing $translate.refresh() every time I update a scope value that needs to be re-translated. I feel like that's clunky, and probably not the way I should be doing it.
Any thoughts?
You definitely should not issue a refresh for this.
just do something like this:
<span> {book.state | translate} </span>
Given that your book model has a member state to reflect it's state.
Whenever the model changes, the value of state will be re-translated.
Create a common service for translation, this will configure our translation code, in particular it will configure the location of our translation files. Create a directory src/common/translation, and a file src/common/translation/translation.js:
http://technpol.wordpress.com/2013/11/02/adding-translation-using-angular-translate-to-an-angularjs-app/
angular.module('angularTranslateApp', ['pascalprecht.translate'])
.config(function($translateProvider, $translatePartialLoaderProvider) {
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: '/UI/assets/translation/{lang}/{part}.json'
}
});
$translateProvider.preferredLanguage('en-AU'); });