Sharing data between controllers - Angularjs - angularjs

i have a problem while im trying to share a data between two controllers.
Here is my code :
<html>
<head>
<title>My Angular App</title>
</head>
<body ng-app="MyTest">
<div ng-controller="ViewController as vmView">
<ul>
<li ng-repeat="singleItem in vmView.allData">
{{ singleItem }}
</li>
</ul>
{{ vmView.checkItOut }}
<input type="button" ng-click="vmView.justClick()" />
</div>
<div ng-controller="AddController as vmAdd">
<form ng-submit="vmAdd.saveChanges()">
<input type="text" ng-model="vmAdd.inputText" />
<input type="submit" />
</form>
</div>
<script src="angular.js"></script>
<script src="app.js"></script>
<script type="application/javascript">
angular.module('MyTest')
.factory('shareDataFactory', function($http, $q) {
var data = {};
data.list = $q.defer();
data.getAllData = function() {
$http.get('http://www.w3schools.com/angular/customers.php')
.then(function(response) {
data.list = $q.resolve(response.data.records);
});
return data.list.promise;
};
data.addData = function(newData) {
data.list.push(newData);
};
return data;
});
angular.module('MyTest')
.controller('ViewController', function ViewController(shareDataFactory) {
var vm = this;
vm.allData = shareDataFactory.getAllData();
vm.checkItOut = "Just checking ..";
vm.justClick = function() {
console.log(vm.allData);
}
});
angular.module('MyTest')
.controller('AddController', function AddController(shareDataFactory) {
var vm = this;
vm.inputText = "Hello";
vm.saveChanges = function() {
shareDataFactory.addData(vm.inputText);
// Clear the data
vm.inputText = "";
};
});
</script>
</body>
</html>
vm.allData its just not updating affter the request come back from the server.
i tried to solve this for a long time but without success.
thanks you everyone and have a lovely week,
rotem

Your code doesn't make much sense:
data.list = $q.defer();
So, data.list is a deferred object. But later
data.list = $q.resolve(response.data.records);
Ah, it's not a deferred anymore: it's being replaced by a resolved promise, unrelated to the promise returned by getAllData(). But later
data.list.push(newData);
Ah, that code thinks it's an array, and not a promise not a deferred.
That can't be right. If you want to be able to push, it must be an array. If you want to populate the array when the http promise is resolved, then push to this aray
It's also unclear what the service should do: it gets data from an HTTP service, but doesn't send the new values to that HTTP service. So, every time you'll call getAllData(), you'll lose the added values.
Anyway:
var list = [];
var getAllData = function() {
$http.get('http://www.w3schools.com/angular/customers.php')
.then(function(response) {
// clear the array
list.splice(0, list.length);
// copy every record to the array
response.data.records.forEach(function(record) {
list.push(record);
});
});
return list;
};
var addData = function(newData) {
list.push(newData);
};
return {
getAllData: getAllData,
addData: addData
};

Here you can find a working version of your code.
When data is loaded, you are replacing the bound list with a new one, so changes aren't getting reflected anymore.
Html
<div ng-controller="ViewController as vmView">
<ul>
<li ng-repeat="singleItem in vmView.allData">
{{ singleItem }}
</li>
</ul>
{{ vmView.checkItOut }}
<input type="button" ng-click="vmView.justClick()" />
</div>
<div ng-controller="AddController as vmAdd">
<form ng-submit="vmAdd.saveChanges()">
<input type="text" ng-model="vmAdd.inputText" />
<input type="submit" />
</form>
</div>
</body>
Javascript
var module = angular.module('MyTest', []);
module.service('shareDataFactory', function($http, $q) {
var data = {
list: []
};
$http.get('http://www.w3schools.com/angular/customers.php')
.then(function(response) {
Array.prototype.push.apply(data.list, response.data.records);
});
return {
getData: function() {
return data;
},
addData: function(newData) {
data.list.push(newData);
}
};
});
module.controller('ViewController', function ViewController($scope, shareDataFactory) {
$scope.allData = shareDataFactory.getData().list;
$scope.checkItOut = "Just checking ..";
$scope.justClick = function() {
console.log($scope.allData);
}
});
module.controller('AddController', function AddController($scope, shareDataFactory) {
$scope.inputText = "Hello";
$scope.saveChanges = function() {
shareDataFactory.addData($scope.inputText);
// Clear the data
$scope.inputText = "";
};
});

Related

Error while retrieving data from local storage

i am unable to retreive the data when i reopen my app.What should i do to permanently save the data
I tried this code:
<body ng-app="starter" ng-controller="Appctrl">
<form data-ng-submit="addTodo()" class="todo-form">
<input type="text" data-ng-model="todoText" placeholder="Enter new ToDo
item" />
<br />
<input type="submit" value="Add Task" />
</form>
<ul class="unstyled">
<li data-ng-repeat="item in todo track by $index">
<input type="text">
<span>{{ item.text }}</span>
</li>
</ul>
</body>
and in app.js:
.controller("Appctrl", function($scope) {
$scope.addTodo = function() {
$scope.text = $scope.todoText;
$scope.todos = [];
$scope.todo.push(text);
$scope.todoText = ''; //clear the input after adding
localStorage.setItem('todo', JSON.stringify($scope.todo));
$scope.saved = localStorage.getItem('todo');
localStorage.setItem('todo', JSON.stringify($scope.saved));
};
});
When retrieving the data from local storage check for existence then JSON.parse(localStorage.getItem('todo')) the get from local storage
In your case:
//you will need to parse the string to store it as an object
$scope.saved = JSON.parse(localStorage.getItem('todo'));
You can use the following factory:
yourApp.factory('$localStorage', ['$window', function($window) {
return {
store: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
storeObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key,defaultValue) {
return JSON.parse($window.localStorage[key] || defaultValue);
}
}
}]);
To use the factory you should inject it in your controller and use it like the following:
//to store
$localStorage.storeObject("sometoken", data);
//to retrieve
$localStorage.getObject("sometoken", "");
i solved my issue:
.controller("Appctrl",function($scope){
$scope.saved = localStorage.getItem('id');
$scope.id = JSON.parse($scope.saved);
localStorage.setItem('id', JSON.stringify($scope.id));
$scope.addTodo = function() {
//$scope.text=$scope.todoText;
$scope.id = [];
$scope.id.push({text:$scope.idText});
$scope.idText = ''; //clear the input after adding
localStorage.setItem('id', JSON.stringify($scope.id));
};
});
Check your code in controller.
You are doing : $scope.todo.push(text); instead of $scope.todos.push(text); itseems

AngularJs requires page refresh after API call

I am writing an angularjs app. The requirement is to display the user's data once the user logs in. So when an user successfully logs in, he/she is routed to the next view. My application is working fine upto this point. Now as the next view loads I need to display the existing records of the user. However at this point I see a blank page, I can clearly see in the console that the data is being returned but it is not binding. I have used $scope.$watch, $scope.$apply, even tried to call scope on the UI element but they all result in digest already in progress. What should I do? The page loads if I do a refresh
(function () {
"use strict";
angular.module("app-newslist")
.controller("newsController", newsController);
function newsController($http,$q,newsService,$scope,$timeout)
{
var vm = this;
$scope.$watch(vm);
vm.news = [];
vm.GetTopNews = function () {
console.log("Inside GetTopNews");
newsService.GetNewsList().
then(function (response)
{
angular.copy(response.data, vm.news);
}, function () {
alert("COULD NOT RETRIEVE NEWS LIST");
});
};
var el = angular.element($('#HidNews'));
//el.$scope().$apply();
//el.scope().$apply();
var scpe = el.scope();
scpe.$apply(vm.GetTopNews());
//scpe.$apply();
}
})();
Thanks for reading
you don't show how you're binding this in your template.. I tried to recreate to give you a good idea.
I think the problem is the way you're handling your promise from your newsService. Try looking at $q Promises. vm.news is being updated by a function outside of angular. use $scope.$apply to force refresh.
the original fiddle is here and a working example here
(function() {
"use strict";
var app = angular.module("app-newslist", [])
.controller("newsController", newsController)
.service("newsService", newsService);
newsController.$inject = ['$http', 'newsService', '$scope']
newsService.$inject = ['$timeout']
angular.bootstrap(document, [app.name]);
function newsController($http, newsService, $scope) {
var vm = this;
vm.news = $scope.news = [];
vm.service = newsService;
console.warn(newsService)
vm.message = "Angular is Working!";
vm.GetTopNews = function() {
console.log("Inside GetTopNews");
newsService.GetNewsList().
then(function(response) {
$scope.$apply(function() {
$scope.news.length > 0 ? $scope.news.length = 0 : null;
response.data.forEach(function(n) {
$scope.news.push(n)
});
console.log("VM", vm);
})
}, function() {
alert("COULD NOT RETRIEVE NEWS LIST");
});
};
}
function newsService($timeout) {
return {
GetNewsList: function() {
return new Promise(function(res, rej) {
$timeout(function() {
console.log("Waited 2 seconds: Returning");
res({
data: ["This should do the trick!"]
});
}, 2000);
})
}
}
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.9/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.min.js"></script>
<body>
<div class="main">
<div class="body" ng-controller="newsController as vm">
Testing: {{ vm.message }}
<br>{{ vm.news }}
<br>{{ vm }}
<br>
<button class="getTopNewsBtn" ng-click="vm.GetTopNews()">Get News</button>
<br>
<ul class="getTopNews">
<li class="news-item" ng-repeat="news in vm.news track by $index">
{{ news | json }}
</li>
</ul>
</div>
</div>
</body>

Ionic/AngularJS & Wordpress API

I'm somewhat new to the JS world, so I'm struggling a bit as to what I did wrong. My sample data from wordpress API is not working. Any ideas what I did wrong:
app.controller('FeedCtrl', function($http, $scope, $ionicLoading) {
console.log("Loading FeedCtrl");
$scope.stories = [];
function loadStories(params, callback) {
$http.get('http://public-api.wordpress.com/rest/v1/freshly-pressed/', {params: params})
.success(function(response) {
var stories = [];
angular.forEach(response.data.children, function(child) {
stories.push(child.data);
});
callback(stories);
});
}
$scope.loadOlderStories = function() {
var params = {};
if ($scope.stories.length > 0) {
params['after'] = $scope.stories[$scope.stories.length - 1].name;
}
loadStories(params, function(olderStories) {
$scope.stories = $scope.stories.concat(olderStories);
$scope.$broadcast('scroll.infiniteScrollComplete');
});
};
$scope.loadNewerStories = function() {
var params = {'before': $scope.stories[0].name};
loadStories(params, function(newerStories) {
$scope.stories = newerStories.concat($scope.stories);
$scope.$broadcast('scroll.refreshComplete');
});
};
I've made a simplified example with your data.
Click the 'Load more' button to retrieve some posts. You should see a list with the title and the author of a post.
EDIT: There appears to be some cross-domain request issues, that's why the 'Load stories' button won't work. Just try to reflect this code inside your controller, it should work.
var app = angular.module('myApp', []);
app.controller('feedCtrl', function ($scope, $http) {
$scope.stories = [];
$scope.loadStories = function loadStories() {
console.log('loading stories');
$http.get('http://public-api.wordpress.com/rest/v1/freshly-pressed/')
.then(function onSuccess(response) {
console.log(response);
$scope.stories = response.data.posts;
}, function onFailed(error) {
console.error('Error:', error)
});
}
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="feedCtrl">
<button data-ng-click="loadStories()">Load stories</button>
<ul>
<li data-ng-repeat="story in stories">Title: {{ story.title }} - {{ story.author.first_name }} {{ story.author.last_name }}</li>
</ul>
</div>
</body>
</html>
Normally we wouldn't handle $http calls in our angular.controller. This needs to be done in an angular.service.

AngularFire $remove item from Array using a variable in Firebase reference does not work

I've been struggling with the following problem:
I'm trying to delete a 'Post' item from a Firebase Array with the $remove AngularFire method which I have implemented in a Angular Service (Factory). This Post is a child of 'Event', so in order to delete it I have to pass this Service a argument with the relevant Event of which I want to delete the post.
This is my controller:
app.controller('EventSignupController', function ($scope, $routeParams, EventService, AuthService) {
// Load the selected event with firebase through the eventservice
$scope.selectedEvent = EventService.events.get($routeParams.eventId);
// get user settings
$scope.user = AuthService.user;
$scope.signedIn = AuthService.signedIn;
// Message functionality
$scope.posts = EventService.posts.all($scope.selectedEvent.$id);
$scope.post = {
message: ''
};
$scope.addPost = function (){
$scope.post.creator = $scope.user.profile.username;
$scope.post.creatorUID = $scope.user.uid;
EventService.posts.createPost($scope.selectedEvent.$id, $scope.post);
};
$scope.deletePost = function(post){
EventService.posts.deletePost($scope.selectedEvent.$id, post);
// workaround for eventService bug:
// $scope.posts.$remove(post);
};
});
And this is my Service (Factory):
app.factory('EventService', function ($firebase, FIREBASE_URL) {
var ref = new Firebase(FIREBASE_URL);
var events = $firebase(ref.child('events')).$asArray();
var EventService = {
events: {
all: events,
create: function (event) {
return events.$add(event);
},
get: function (eventId) {
return $firebase(ref.child('events').child(eventId)).$asObject();
},
delete: function (event) {
return events.$remove(event);
}
},
posts: {
all: function(eventId){
var posts = $firebase(ref.child('events').child(eventId).child('posts')).$asArray();
return posts;
},
createPost: function (eventId, post) {
// this does work
var posts = $firebase(ref.child('events').child(eventId).child('posts')).$asArray();
return posts.$add(post);
},
deletePost: function (eventId, post) {
// this does not work
var posts = $firebase(ref.child('events').child(eventId).child('posts')).$asArray();
return posts.$remove(post);
}
}
};
return EventService;
});
When I try to delete the link tag just freezes and no error logging appears in the console. While if I call $remove on my $scope.posts directly in my controller it magically works.. Furthermore my Post is not removed from my Firebase DB.
Another weird thing is that 'CreatePost' works perfectly fine using the same construction.
My view:
<div class="col-xs-8 col-xs-offset-2 well">
<form ng-submit="addPost()" ng-show="signedIn()">
<input type="text" ng-model="post.message" />
<button type="submit" class="btn btn-primary btn-sm">Add Post</button>
</form>
<br>
<div class="post row" ng-repeat="post in posts">
<div>
<div class="info">
{{ post.message }}
</div>
<div>
<span>submitted by {{ post.creator }}</span>
delete
</div>
<br>
</div>
</div>
</div>
P.s. I'm not too sure that my 'Service' is implemented in the best possible way.. I couldn't find another solution for doing multiple firebase calls
var posts = $firebase(ref.child('events').child(eventId).child('posts')).$asArray();
within the Post part of my EventService, because it depends on eventId in each CRUD operation. Any ideas would be very welcome :)
The easiest way for me was to use this:
var ref= new Firebase('https://Yourapp.firebaseio.com/YourObjectName');
ref.child(postId).remove(function(error){
if (error) {
console.log("Error:", error);
} else {
console.log("Removed successfully!");
}
});
The only way I'm able to remove the item is using a loop on the array we get from firebase.
var ref= new Firebase('https://Yourapp.firebaseio.com/YourObjectName');
var arr_ref=$firebaseArray(ref);
for(var i=0;i<arr_ref.length;i++){
if(key==arr_ref[i].$id){
console.log(arr_ref[i]);
arr_ref.$remove(i);
}
}

How can I use the exact same array from one service in two controllers?

I have this code:
controller:
function deleteRootCategory(){
$scope.rootCategories[0] = '';
}
function getCategories(){
categoryService.getCategories().then(function(data){
$scope.rootCategories = data[0];
$scope.subCategories = data[1];
$scope.titles = data[2];
});
}
getCategories();
service:
var getCategories = function(){
var deferred = $q.defer();
$http({
method:"GET",
url:"wikiArticles/categories"
}).then(function(result){
deferred.resolve(result);
});
}
return deferred.promise;
}
html:
<div ng-controller="controller">
<div ng-repeat="root in rootCategories"> {{root}} </div>
<div ng-repeat="sub in subCategories"> {{sub}} </div>
<div ng-repeat="title in titles">{{title}}</div>
</div>
html2:
<div ng-controller="controller">
<div ng-include src="html"></div>
<button ng-click="deleteRootCategory()">Del</button>
</div>
When I click the deleteRootCategory-button the array $scope.rootCategories is updated, but the view won't ever change.
What am I missing?
Thanks
You will probably want to have a broadcast event set up when the value is changed in the service. Something like this.
.service("Data", function($http, $rootScope) {
var this_ = this,
data;
$http.get('wikiArticles/categories', function(response) {
this_.set(response.data);
}
this.get = function() {
return data;
}
this.set = function(data_) {
data = data_;
$rootScope.$broadcast('event:data-change');
}
});
Have both controllers waiting for the event, and using the set to make any changes to the array.
$rootScope.$on('event:data-change', function() {
$scope.data = Data.get();
}
$scope.update = function(d) {
Data.set(d);
}

Resources