LocalStorage with directive in AngularJS - angularjs

I use ngStorage (https://github.com/gsklee/ngStorage) for storing some data in the localStorage of the browser.
I have this markup
<ul class="cards">
<li ng-repeat="card in cards">
<card></card>
</li>
</ul>
With a "card" (as u can see) directive, that stores my template for each card.
In my Controller I have this method to push a card in the ng-repeat Array of cards:
angular.controller('CustomerController', function($scope, $localStorage, $sessionStorage) {
$scope.cards = [];
$scope.addCardRed = function() {
return $scope.cards.push(new Card("red"));
};
(...)
});
That works so far. But I can't accomplish to store the cards in my ul. I tried some variations of:
(...)
$scope.$storage = $localStorage;
$scope.cards = [];
$localStorage.cards = [];
$localStorage.cards = $scope.cards;
But either my cards won't displayed in the list anymore or the list won't be stored. What can I do to store my card elements in the list? What am I doing wrong?

I think, your Card is not a Simple JavaScript Object. therefore you may want to use something like this:
angular.module('storage',[]).factory('cardStorage',function(){
var key = 'cards';
var store = localStorage;
// Card has to be JSON serializable
function assign(value){store[key]=JSON.stringify(value)};
// return Card instances
function fetch(){return (JSON.parse(store[key])||[]).map(
function(card){return new Card(card);
})};
return {
bind:function(scope,attribute,defaults){
// read from storage - in case no data in scope
if(!(attribute in scope)){
scope[attribute]=fetch();
}
// observe changes in cars and persist them
scope.$watch(attribute,function(next,prev){
assign(next);
},true);
}
}
});
and in your Controller
function(scope,cardStorage){
cardStorage.bind('cards');
}
or you can use :
https://github.com/agrublev/angularLocalStorage

Related

angulajs data on the page is not loading after route redirection

when I am at the home page and click on the link in the navigation bar
<li class="nav-item" ng-show="currentUser">
<a class="nav-link" ng-show="currentUser"
ng-href="#/pictures"">Pictures</a>
</li>
It goes to the page, I can see the data is downloaded but it is not shown in the UI when update $scope.urlListUI.
urlListInRoomUnits=loadPicture(filePathInRoomUnitPicture);
$scope.urlListUI=urlListInRoomUnits;
$scope.$apply();
console.log('update ui: '+urlListInRoomUnits);
however, if I refresh the page, it will work.
the UI code
<div ng-repeat = "urlRecord in urlListUI">
<p>{{urlRecord[1]}}</p>
<img ngf-src="urlRecord[0]" class="img-thumbnail">
</div>
the function: loadPicture(filePathInRoomUnitPicture)
function loadPicture(pictureTypeFolder){
console.log('loadpicture is running, input parameter:'+pictureTypeFolder);
var urlList=[];
$scope.whereThePictureIs=pictureTypeFolder;
//list image from firebase storage
var storageRefDownloadByPictureType = storageRef.child('airconPicture').child(pictureTypeFolder);
storageRefDownloadByPictureType.listAll()
.then(function(result) {
console.dir(result);
result.items.forEach(function(imageRef) {
// And finally display them
imageRef.getDownloadURL()
.then(function(url){
// TODO: Display the image on the UI
urlList.push([url,imageRef.name]);
})
.catch(function(error) {
// Handle any errors
});
});// end of for each download
})// end of list all promise
.catch(function(error) {
// Handle any errors
});
return urlList;
};// end of load Pciture by type
thanks for helping or direct me to the right source.
So what I see, first, you try to resolve storageRefDownloadByPictureType.listAll()
After resolving (let's say 1 sec), you run in a loop on results and try to resolve a list of items:
result.items.forEach(function(imageRef) {
imageRef.getDownloadURL().then(function(url){
})
You resolve all at once, let's say, another 1 sec.
Your method does not return promise but empty urlList because you populate it in the next 2 seconds.
So instead urlListInRoomUnits=loadPicture(filePathInRoomUnitPicture);
It should be something like (you can write loadPicture in some service, lets say MyService):
MyService.loadPicture(filePathInRoomUnitPicture).then(function (urls) {
//here you get all your results
$scope.urlListUI = //...
});
and now loadPicture in MyService:
this.loadPicture = function(filePathInRoomUnitPicture){
//...
return storageRefDownloadByPictureType.listAll().then(function(result) {
// create list of promises:
var promises = [];
result.items.forEach(function(imageRef) {
promises.push(imageRef.getDownloadURL());
})
// chain promises
return $q.all(promises);
};

How to wait for response from service in ng-repeat

I am trying to display the items using ng-repeat and when the list is initailly loading , trying to call another service to get the details about the first item.
Here is my code:
<div ng-repeat="item in itemList">
<div ng-click="setCurrentItem(item,$index)" ng-init="initCurrentItem(item,$index)">
item.id
</div>
</div>
In controller:
function init(){
itemService.loadItem();
}
$scope.itemList = function(){
return itemService.getItemsList();
}
from this service I am getting the following data :
itemName:x001,
item.id:10
itemName:x002,
item.id:20,
itemName:x003,
item.id:30.
I am calling another service to get itemDetails.
$scope.currentItemDetails ={};
$scope.currentItemDetails.id ='';
$scope.initCurrentItem(item.index){
if(scope.currentItemDetails.id === ''){
$scope.setCurrentItem(item.index);
}
}
$scope.setCurrentItem = function(item,index){
item.index = index;
itemService.loadItemDetails(item.id).then(function(response){
if(angular.isDefined(response)){
$scope.currentItemDetails = response.data;
}
});
when the list loading initailly and calling initCurrentItem, the currentItemDetails holding last item (itemName:x003,id:30). ng-repeat is repeat the values without waiting response from the service. How do I wait in the loop until I get response from first item?
Just use the same logic in init method as you have in the other example - with .then( etc. And assign value to the repeating variable itemList. Then table HTML will be refreshed automagically when the data arrives and Promise will be resolved:
<div ng-repeat="item in itemList">
function init(){
itemService.loadItem().then(function(response){
if(angular.isDefined(response)){
$scope.itemList = response.data;
}
});
}
UPD
try calling initCurrentItem after the data is loaded
function init(){
itemService.loadItem().then(function(response){
if(angular.isDefined(response)){
$scope.itemList = response.data;
//here we iterate received array $scope.itemList and call initCurrentItem on each of them
$scope.itemList.forEach(function(item, i){
$scope.initCurrentItem(item, i);
});
}
});
}

Reading data from firebase in angularfire

I have an app where I need to store artists and their details in database.Now I want to retrieve all the artists and render some of their details in front end.How to do that.
Secondly, if I get the artist rating in some input field by using ng-model, then how to store that value in a particular artist to update details.
The database structure is:
{
"artists": {
"Atif":{
"name":"atif",
"rating":8
},
"Himesh":{
"name":"himesh",
"rating":5
}
}
}
and this is angular.js
(function()
{
var app = angular.module("myapp", ["firebase"]);
app.controller("maincontroller", function($scope, $firebaseObject,$firebaseArray)
{
var ref = new Firebase("https://gigstart.firebaseio.com/");
var artists=ref.child("artists");
// download the data into a local object
$scope.data = $firebaseObject(ref);
// putting a console.log here won't work, see below
ref.on("value", function(snapshot)
{
console.log(snapshot.val());
}, function (errorObject)
{
console.log("The read failed: " + errorObject.code);
});
var artistsRef=new Firebase("https://gigstart.firebaseio.com//artists");
}); //end of controller
Now I want to render the name and rating of each artist in front end.Can I do something like
<div ng-repeat="artist in artists">
{{artist.name}}
{{artist.rating}}
</div>
You have a list of artists, which you want to ng-repeat over in your Angular view. You can accomplish that by:
app.controller("maincontroller", function($scope, $firebaseArray)
{
var ref = new Firebase("https://gigstart.firebaseio.com/");
var artists = ref.child("artists");
$scope.artists = new $firebaseArray(artists);
}
Please take a moment to go through the AngularFire quickstart before starting on your own project. This is covered in step 5.

How to create service that will store currently active menu?

By clicking the link i change view, this re-instantiating my controller. This is why the activeMenu is empty. If icreate a service and store the currently active menu in there, it won't be empty.How can i create service to do that? This is my first time that i need to create service?This is my plnkr... http://plnkr.co/edit/gJko3umteXXEye7o9StR?p=preview
Problem is when user click on menu from layout then this re-instantiating my controller
Layout:
<li class="dropdown">
<ul class="submenu">
<li>#Translate("MY_ACCOUNT")</li>
<li ng-click="GetLoader();">#Translate("SETTINGS")</li>
<li ng-click="GetLoader();">#Translate("TICKET_HISTORY")</li>
<li ng-click="GetLoader();">#Translate("TRANSACTIONS")</li>
<li ng-click="GetLoader();">#Translate("BONUS_ACCOUNT")</li>
<li>#Translate("ODDS_REPRENSETATION")</li>
<li>#Translate("HELP")</li>
<li>#Translate("LOGOUT")</li>
</ul> </li>
You can do it like this:
app.service('navigation', function () {
this.activeLink = '';
});
app.controller('MainCtrl', function($scope, navigation) {
$scope.activeMenu = 'Home';
$scope.activeLink = navigation.activeLink;
$scope.changeActiveLink = function(link) {
$scope.activeLink = link;
this.activeLink = link;
}
});
The service is a singleton, it's intatiaded once per you application load, so it will keep the assigned value between diffent states of your app.
You can make it a bit smarter if you won't store a simple string value but an object - this way we'll be able to keep the reference to the service's value rather than the value itself and we won't need to set both $scope.activeLink = link; and this.activeLink = link; explicitly:
app.service('navigation', function () {
this.active = {
link: '',
menu: 'Home'
};
});
app.controller('MainCtrl', function($scope, navigation) {
$scope.activenav = navigation.active;
$scope.changeActiveLink = function(link) {
navigation.active.link = link;
}
});
(just remember to make necessary changes in your html code in that second case)

AngularJS watch service value change instead of scope inheritance

I just give a try to AngularJS. I try to do something quite simple but I'd like to do it the good way.
I got a list of items in a table which displays name and quantity for each item.
I have a form under the table.
When I click on an item name from the table I'd like the given item to be updatable through the form.
I achieve to do thing with scope inheritance as in fiddle http://jsfiddle.net/5cRte/1/
View :
<tr ng-repeat="item in items">
<td>{{item.name}}</td>
<td>{{item.quantity}}</td>
</tr>
Controllers :
function ItemListController($scope){
$scope.items = [{name:'item1', quantity:10}, {name:'item2', quantity:5}];
$scope.selectCurrentItem = function(currentItem) {
$scope.currentItem = currentItem;
}
}
function ItemFormController($scope){
$scope.$watch('currentItem', function() {
$scope.item = $scope.currentItem;
});
}
But has I read in some topics, it is not a good practice to couple controllers scopes this way, and preferably I'll wan't to use a service to store variables shared between controllers.
I was able to put a static variable in a service and retrieve it in another controller, but I can't make it updated when clicking on the item from the table, as watch not working on services variable. Have you an hint, for this ?
Thanks in advance
I don't know whether this is optimal but this what I could come up with
angular.module('myApp', []);
angular.module('myApp').factory('myService', function(){
var items = [{name:'item1', quantity:10}, {name:'item2', quantity:5}, {name:'item3', quantity:50}];
var current = {};
return {
getItems: function(){
return items;
},
setCurrentItem: function(item){
current.item = item;
},
removeCurrentItem: function(){
delete current.item;
},
getCurrent: function(){
return current;
}
}
});
function ItemListController($scope, myService){
$scope.items = myService.getItems();
$scope.selectCurrentItem = function(currentItem) {
myService.setCurrentItem(currentItem);
}
}
function ItemFormController($scope, myService){
$scope.current = myService.getCurrent();
}
Demo: Fiddle

Resources