AngularJs: saving data locally in angularJs - angularjs

i have a project am working about a shopping list and am making in such a way that the user types the item he wants to add and whenever he adds it displays that he has dded a particular product and not to forget he has the ability to remove any product from the list. But when never i reload the page it displays empty even though i already added some item previously..this is the code
var app = angular.module("shoppingList",[]);
app.controller("myCtrl",function($scope){
$scope.goods = []
var taskData = localStorage()
$scope.addItem = function(){
$scope.errorText = "";
if(!$scope.addNew){return;}
if($scope.goods.indexOf($scope.addNew) == -1){
$scope.goods.push($scope.addNew);
}else{
$scope.errorText = "The Item is already in your shopping list"
}
};
$scope.removeItem = function(x){
$scope.errorText = ""
$scope.goods.splice(x,1);
}
})

It is a good idea to use https://github.com/gsklee/ngStorage in your app, because it will let you use localstorage the angular way. so to rewrite your code with ngStorage:
var app = angular.module("shoppingList",['ngStorage']);
app.controller("myCtrl",function($scope,$localStorage){
$scope.goods = $localStorage.goods || [];
var taskData = localStorage()
$scope.addItem = function(){
$scope.errorText = "";
if(!$scope.addNew){return;}
if($scope.goods.indexOf($scope.addNew) == -1){
$scope.goods.push($scope.addNew);
$localStorage.goods.push($scope.addNew);
}else{
$scope.errorText = "The Item is already in your shopping list"
}
};
$scope.removeItem = function(x){
$scope.errorText = ""
$scope.goods.splice(x,1);
$localStorage.goods.splice(x,1);
}
})
hope this works for you

Related

Doing basic validation in ionic

Hi Im trying my hands on ionic and angularjs. I have a sample code that deals with the phone-list. The working of the code is to add the phone number to the list and delete the selected and also when a number is entered it should check if the number exist there, if the number is not in existence then it should add it. The problem I face here is in checking the existence of the phone number in the list.
link
$scope.phonelist = [];
$scope.add = function() {
$scope.phonelist.push($scope.phone);
$scope.phone = {};
}
$scope.removeSelected = function() {
var i = $scope.phonelist.length;
// reversed loop because you change the array
while (i--) {
var phone = $scope.phonelist[i];
if (phone.checked) {
$scope.phonelist.splice(i, 1);
}
$scope.phonelist = [];
var added;
$scope.add = function() {
added = false;
for (var j=0;j<$scope.phonelist.length;j++) {
if (angular.equals($scope.phonelist[j], $scope.phone)) {
added=true;
}
}
if (!added) {
$scope.phonelist.push($scope.phone);
$scope.phone = {};
} else {
alert('error');
}
}
Update your controller like this for add function . Thanks

Updating icon in real tme in Ionic

I have a favourites icon that should change from an outline to solid but it will only do this once the page has been reloaded. Is there any way to update this in real time without reloading the page.
It should update the ng-class to change from an outline to solid.
<i ng-class="{'icon ion-android-star': favicon(office.id), 'icon ion-android-star-outline': !favicon(office.id)}"
ng-click="togglefav(office.id); $event.stopPropagation();"></i>
This checks if the value is in local storage, then returns true or false.
.controller('APICtrl', function($scope, $http, $localstorage, $window, $state, $sce) {
// Search function
$scope.query = {}
$scope.queryBy = '$'
// gets the data from offices.json
$http.get('js/offices.json').then(function(resp) {
console.log('Success', resp);
$scope.offices = resp.data.office;
}, function(err) {
console.error('ERR', err);
// err.status will contain the status code
});
$scope.sce = function(loc1){
return $sce.trustAsHtml("https://www.google.com/maps/geocoding/json?address=loc1&key=AIzaSyBGAHnplGPjFoVvShk6Tsna3-DN8rHQBI8")
}
//retrieves localstorage array
//$scope.favourties= JSON.parse($window.localStorage['fav']);
//$scope.favourites = $window.localStorage['favs'] ? JSON.parse($window.localStorage['favs']) : []
//checks if the array if is in localstorage, if it isnt then it adds an array, if it is it parses the array
if($window.localStorage['fav']){
$scope.favorites = JSON.parse($window.localStorage['fav']);
var fav = JSON.parse($window.localStorage['fav']);
} else {
var fav = [];
$window.localStorage['fav'] = JSON.stringify(fav);
}
console.log(fav);
$scope.togglefav = function(id) {
//checks if the id being passed in is already in the array
//if it isn't it will add it to the beginning array then stringify it
if (fav.indexOf(id) == -1){
fav.unshift(id);
console.log(fav);
$window.localStorage['fav'] = JSON.stringify(fav);
}
//if it is then it will remove it from the array and stringify the array
else{
fav.splice(fav.indexOf(id), 1);
$window.localStorage['fav'] = JSON.stringify(fav);
console.log(fav);
}
}
//last viewed office view
if($window.localStorage['last']){
$scope.favorites = JSON.parse($window.localStorage['last']);
var last = JSON.parse($window.localStorage['last']);
} else {
var last = [];
$window.localStorage['last'] = JSON.stringify(last);
}
console.log(last);
$scope.lastview = function(id) {
//checks if the id being passed in is already in the array
//if it isn't it will add it to the beginning array then stringify it
var c = JSON.parse($window.localStorage['last']);
if (last.indexOf(id) == -1){
if (c.length > 3){
last.pop();
}
last.unshift(id);
$window.localStorage['last'] = JSON.stringify(last);
}
}
// used to change the favourites icon based on if its in the local storage or not
var e = JSON.parse($window.localStorage['fav']);
$scope.favicon = function(office){
return e.indexOf(office) !== -1;
};
// used to check if the item is in localstorage and check it against the json array
// if it matches then it will return true and be displayed
// this one is used for favourited offices
$scope.ifinfav1 = function(office){
return e.indexOf(office.id) !== -1;
};
var f = JSON.parse($window.localStorage['last']);
// this one is used for last viewed offices
$scope.ifinfav2 = function(office){
return f.indexOf(office.id) !== -1;
};
})
(function(angular) {
'use strict';
angular.module('includeExample', ['ngAnimate'])
.controller('ExampleController', ['$scope', '$q',
function($scope, $q) {
$scope.office = {
id: 'here'
};
//var e = JSON.parse($window.localStorage['fav']);
var e = ['here']
$scope.favicon = function(office) {
return e.indexOf(office) !== -1;
};
$scope.togglefav = function(office) {
if ($scope.office.id === 'here')
$scope.office.id = 'here2';
else
$scope.office.id = 'here';
};
}
]);
})(window.angular);
.ion-android-star{
color:red;
}
.ion-android-star-outline{
color:blue;
}
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular-animate.js"></script>
<body ng-app="includeExample">
<div ng-controller="ExampleController">
<i ng-class="{'icon ion-android-star': favicon(office.id), 'icon ion-android-star-outline': !favicon(office.id)}" ng-click="togglefav(office.id); "> Content</i> (click me)
</div>
</body>
you can use the $scope in office variable.
when you change the office will be visible to the template as well.

angular push result to controller

(was not sure what to have as a title, so if you have a better suggestion, feel free to come up with one - I will correct)
I am working on an angular application where I have some menues and a search result list. I also have a document view area.
You can sort of say that the application behaves like an e-mail application.
I have a few controllers:
DateCtrl: creates a list of dates so the users can choose which dates they want to see posts from.
SourceCtrl: Creates a list of sources so the user can choose from which sources he/she wants to see posts from.
ListCtrl: The controller populating the list. The data comes from an elastic search index. The list is updated every 10-30 seconds (trying to find the best interval) by using the $interval service.
What I have tried
Sources: I have tried to make this a filter, but a user clicks two checkboxes the list is not sorted by date, but on which checkbox the user clicked first.
If it is possible to make this work as a filter, I'd rather continue doing that.
The current code is like this, it does not do what I want:
.filter("bureauFilter", function(filterService) {
return function(input) {
var selectedFilter = filterService.getFilters();
if (selectedFilter.length === 0) {
return input;
}
var out = [];
if (selectedFilter) {
for (var f = 0; f < selectedFilter.length; f++) {
for (var i = 0; i < input.length; i++) {
var myDate = input[i]._source.versioncreated;
var changedDate = dateFromString(myDate);
input[i]._source.sort = new Date(changedDate).getTime();
if (input[i]._source.copyrightholder === selectedFilter[f]) {
out.push(input[i]);
}
}
}
// return out;
// we need to sort the out array
var returnArray = out.sort(function(a,b) {
return new Date(b.versioncreated).getTime() - new Date(a.versioncreated).getTime();
});
return returnArray;
} else {
return input;
}
}
})
Date: I have found it in production that this cannot be used as a filter. The list of posts shows the latest 1000 posts, which is only a third of all posts arriving each day. So this has to be changed to a date-search.
I am trying something like this:
.service('elasticService', ['es', 'searchService', function (es, searchService) {
var esSearch = function (searchService) {
if (searchService.field === "versioncreated") {
// doing some code
} else {
// doing some other type of search
}
and a search service:
.service('searchService', function () {
var selectedField = "";
var selectedValue = "";
var setFieldAndValue = function (field, value) {
selectedField = field;
selectedValue = value;
};
var getFieldAndValue = function () {
return {
"field": selectedField,
"value": selectedValue
}
};
return {
setFieldAndValue: setFieldAndValue,
getFieldAndValue: getFieldAndValue
};
})
What I want to achieve is this:
When no dates or sources are clicked the whole list shall be shown.
When Source or Date are clicked it shall get the posts based on these selections.
I cannot use filter on Date as the application receives some 3000 posts a day and so I have to query elastic search to get the posts for the selected date.
Up until now I have put the elastic-search in the listController, but I am now refactoring so the es-search happens in a service. This so the listController will receive the correct post based on the selections the user has done.
Question is: What is the best pattern or method to use when trying to achieve this?
Where your data is coming from is pretty irrelevant, it's for you to do the hook up with your data source.
With regards to how to render a list:
The view would be:
<div ng-controller='MyController as myCtrl'>
<form>
<input name='searchText' ng-model='myCtrl.searchText'>
</form>
<ul>
<li ng-repeat='item in myCtrl.list | filter:myCtrl.searchText' ng-bind='item'></li>
</ul>
<button ng-click='myCtrl.doSomethingOnClick()'>
</div>
controller would be:
myApp.controller('MyController', ['ElasticSearchService',function(ElasticSearchService) {
var self = this;
self.searchText = '';
ElasticSearchService.getInitialList().then(function(list) {
self.list = list;
});
self.doSomethingOnClick = function() {
ElasticSearchService.updateList(self.searchText).then(function(list) {
self.list = list;
});
}
}]);
service would be:
myApp.service('ElasticSearchService', ['$q', function($q) {
var obj = {};
obj.getInitialList = function() {
var defer = $q.defer();
// do some elastic search stuff here
// on success
defer.resolve(esdata);
// on failure
defer.reject();
return defer.promise();
};
obj.updateList = function(param) {
var defer = $q.defer();
// do some elastic search stuff here
// on success
defer.resolve(esdata);
// on failure
defer.reject();
return defer.promise();
};
return obj;
}]);
This code has NOT been tested but gives you an outline of how you should approach this. $q is used because promises allow things to be dealt with asynchronously.

AngularJS, Add Rows

Morning,
We are trying to implement this add row Plunkr, it seems to work however our input data seems to repeat. Does anyone know of a solution to add a unique id to preview duplicated fields ?
Here is our current Plunkr and LIVE example.
$scope.addRow = function(){
var row = {};
$scope.productdata.push(row);
};
$scope.removeRow = function(index){
$scope.productdata.splice(index, 1);
};
$scope.formData you have is not an array, but just one object. All your rows are bound to that object and hence all of them reference the same data.
The reason you get a new row added is because your ng-repeat is bound to $scope.productData and you add extra record in it. You should bind your form elements to the properties in the row object that you create
a simple example is :
In your template
<div ng-repeat="product in products">
<input type="text" ng-model="product.title">
</div>
In your controller
$scope.addProduct = function(){
var product = {};
$scope.productData.add(product);
}
You'd then always only work with the productData array and bind your model to them.
Even in your backend calls, you'd use productData instead of your formData.
Hope this helps.
U can use a filter : This will return Unique rows only
app.filter('unique', function () {
return function (items, filterOn) {
if (filterOn === false) {
return items;
}
if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
var hashCheck = {}, newItems = [];
var extractValueToCompare = function (item) {
if (angular.isObject(item) && angular.isString(filterOn)) {
return item[filterOn];
} else {
return item;
}
};
angular.forEach(items, function (item) {
var valueToCheck, isDuplicate = false;
for (var i = 0; i < newItems.length; i++) {
if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
newItems.push(item);
}
});
items = newItems;
}
return items;
};
});
I think the reason why this is happening is that the addRow() function is just pushing an empty son object into the $scope.productdata array, whereas all input fields are bound to $scope.formData[product.WarrantyTestDescription]. I think you mean to bind the input fields to the properties of the product object.

accessing items in firebase

I'm trying to learn firebase/angularjs by extending an app to use firebase as the backend.
My forge looks like this
.
In my program I have binded firebaseio.com/projects to $scope.projects.
How do I access the children?
Why doesn't $scope.projects.getIndex() return the keys to the children?
I know the items are in $scope.projects because I can see them if I do console.log($scope.projects)
app.js
angular.module('todo', ['ionic', 'firebase'])
/**
* The Projects factory handles saving and loading projects
* from localStorage, and also lets us save and load the
* last active project index.
*/
.factory('Projects', function() {
return {
all: function () {
var projectString = window.localStorage['projects'];
if(projectString) {
return angular.fromJson(projectString);
}
return [];
},
// just saves all the projects everytime
save: function(projects) {
window.localStorage['projects'] = angular.toJson(projects);
},
newProject: function(projectTitle) {
// Add a new project
return {
title: projectTitle,
tasks: []
};
},
getLastActiveIndex: function () {
return parseInt(window.localStorage['lastActiveProject']) || 0;
},
setLastActiveIndex: function (index) {
window.localStorage['lastActiveProject'] = index;
}
}
})
.controller('TodoCtrl', function($scope, $timeout, $ionicModal, Projects, $firebase) {
// Load or initialize projects
//$scope.projects = Projects.all();
var projectsUrl = "https://ionic-guide-harry.firebaseio.com/projects";
var projectRef = new Firebase(projectsUrl);
$scope.projects = $firebase(projectRef);
$scope.projects.$on("loaded", function() {
var keys = $scope.projects.$getIndex();
console.log($scope.projects.$child('-JGTmBu4aeToOSGmgCo1'));
// Grab the last active, or the first project
$scope.activeProject = $scope.projects.$child("" + keys[0]);
});
// A utility function for creating a new project
// with the given projectTitle
var createProject = function(projectTitle) {
var newProject = Projects.newProject(projectTitle);
$scope.projects.$add(newProject);
Projects.save($scope.projects);
$scope.selectProject(newProject, $scope.projects.length-1);
};
// Called to create a new project
$scope.newProject = function() {
var projectTitle = prompt('Project name');
if(projectTitle) {
createProject(projectTitle);
}
};
// Called to select the given project
$scope.selectProject = function(project, index) {
$scope.activeProject = project;
Projects.setLastActiveIndex(index);
$scope.sideMenuController.close();
};
// Create our modal
$ionicModal.fromTemplateUrl('new-task.html', function(modal) {
$scope.taskModal = modal;
}, {
scope: $scope
});
$scope.createTask = function(task) {
if(!$scope.activeProject || !task) {
return;
}
console.log($scope.activeProject.task);
$scope.activeProject.task.$add({
title: task.title
});
$scope.taskModal.hide();
// Inefficient, but save all the projects
Projects.save($scope.projects);
task.title = "";
};
$scope.newTask = function() {
$scope.taskModal.show();
};
$scope.closeNewTask = function() {
$scope.taskModal.hide();
};
$scope.toggleProjects = function() {
$scope.sideMenuController.toggleLeft();
};
// Try to create the first project, make sure to defer
// this by using $timeout so everything is initialized
// properly
$timeout(function() {
if($scope.projects.length == 0) {
while(true) {
var projectTitle = prompt('Your first project title:');
if(projectTitle) {
createProject(projectTitle);
break;
}
}
}
});
});
I'm interested in the objects at the bottom
console.log($scope.projects)
Update
After digging around it seems I may be accessing the data incorrectly. https://www.firebase.com/docs/reading-data.html
Here's my new approach
// Load or initialize projects
//$scope.projects = Projects.all();
var projectsUrl = "https://ionic-guide-harry.firebaseio.com/projects";
var projectRef = new Firebase(projectsUrl);
projectRef.on('value', function(snapshot) {
if(snapshot.val() === null) {
console.log('location does not exist');
} else {
console.log(snapshot.val()['-JGTdgGAfq7dqBpSk2ls']);
}
});
$scope.projects = $firebase(projectRef);
$scope.projects.$on("loaded", function() {
// Grab the last active, or the first project
$scope.activeProject = $scope.projects.$child("a");
});
I'm still not sure how to traverse the keys programmatically but I feel I'm getting close
It's an object containing more objects, loop it with for in:
for (var key in $scope.projects) {
if ($scope.projects.hasOwnProperty(key)) {
console.log("The key is: " + key);
console.log("The value is: " + $scope.projects[key]);
}
}
ok so val() returns an object. In order to traverse all the children of projects I do
// Load or initialize projects
//$scope.projects = Projects.all();
var projectsUrl = "https://ionic-guide-harry.firebaseio.com/projects";
var projectRef = new Firebase(projectsUrl);
projectRef.on('value', function(snapshot) {
if(snapshot.val() === null) {
console.log('location does not exist');
} else {
var keys = Object.keys(snapshot.val());
console.log(snapshot.val()[keys[0]]);
}
});
$scope.projects = $firebase(projectRef);
$scope.projects.$on("loaded", function() {
// Grab the last active, or the first project
$scope.activeProject = $scope.projects.$child("a");
});
Note the var keys = Object.keys() gets all the keys at firebaseio.com/projects then you can get the first child by doing snapshot.val()[keys[0])

Resources