I have an angular app that supposed to work with json-server for retrieving data and adding new data (users feedback). so I have json database with some arrays and one of them is "feedbacks":[] which is currently empty. on PUT method I get:
PUT /feedbacks 404 from server and this is chrome console PUT http://localhost:3000/feedbacks 404 (Not Found).
this is my service:
angular.module('myApp')
.constant("baseURL", "http://localhost:3000/")
.service('feedbackService',['$resource','baseURL',function($resource,baseURL){
this.getFeedback=function(){
return $resource(baseURL+"feedbacks/:date",null,{
'update':{
method:'PUT'
}
});
};
}]);
this is the controller:
// contactus.html controllers
.controller('ContactController', ['$scope', function($scope) {
$scope.feedback = {firstName: "",lastName: "",email: "",date: ""};
}])
// Feedback form controller
.controller('FeedbackController', ['$scope', 'feedbackService', function($scope, feedbackService) {
$scope.feedbacks = feedbackService.getFeedback().query(function(response) {
$scope.feedbacks = response;
});
$scope.sendFeedback = function() {
$scope.feedback.date = new Date().toISOString();
$scope.feedbacks.push($scope.feedback);
feedbackService.getFeedback().update($scope.feedbacks);
$scope.feedbackForm.$setPristine();
$scope.feedback = {firstName: "",lastName: "",email: "", date:""};
};
}])
getFeedbacks() method works and server send 200, but for PUT I receive 404.
OK I solved it :)) a very silly mistake. there was no need for push and then update as I wanted to create new object inside the array.
$scope.feedback.date = new Date().toISOString();
feedbackService.getFeedback().save($scope.feedback);
and also I changed the service to:
return $resource(baseURL+"feedbacks/:id",null,{
to have auto incremental id for each object
Related
It seems to be very very simple. But I can't do it.
I just want to get a value of my Firebase DB in my controller.
The Firebase Database is like this:
users {
30549545 {
name: "Marcelo"
lastName: "Forclaz"
years: 24
}
}
In my controller I wrote the following code:
app.controller('usersCtrl', function($scope, $firebaseArray) {
var ref = firebase.database().ref('users');
$scope.userdata = $firebaseArray(ref);
});
In the ngRepeat of the HTML code the iteration works fine. But I need to get the "years" value in my controller to use it to another command, ¿How can I do it? I've tried of several deferents ways but I didn't get the wished result. I realized that retrieving data from Firebase width AngularJS is not so easy than make it width simple and pure JavaScript.
You have to wait until userdata loaded:
app.controller('usersCtrl', function($scope, $firebaseArray) {
var ref = firebase.database().ref('users');
$scope.userdata = $firebaseArray(ref);
$scope.userdata.$loaded()
.then(function(){
console.log($scope.userdata);
});
});
Finally, I've got it!
$scope.userdata.$ref().once('value', function(snap) {
angular.forEach(snap.val(), function(index)) {
console.log(index.years)
}
}
I'm very new to AngularJS and programming aswell, so it can be easy question for you but I'm struggling with it for plenty of hours and can't get my thinking straight.
So, my goal is simple, to have facebook login on my app (webpage), I'm using Ciul angular-facebook module, this actually works but not in the way I want it. When user loggs I want to show his name and photo, but now I have to manually reload page, then it shows, until then it won't. Also I'm storing logged user into localStorage (works ok).
The problem is that after logging in the data aren't updated. In my html code I tried to call them from controller or service, but both had old data, and I don't know how to update it without reloading the page. The most interesting part is when I try it with simple variable and it works like a charm.
Here is my Service
app.factory('mainService', ['$window', '$location', '$route', '$filter', 'Facebook', function (win, $location, $route, $filter, Facebook) {
var scope = {
fbLogin: false,
fbUid: 0,
fbAccessToken: 0,
vkLogin: false
};
var user = {};
if(localStorage.getItem('user') != null) {
user = JSON.parse(localStorage.getItem('user'));
} else {
user = null;
}
return {
scope : scope,
user : user,
fbLogin : function () {
Facebook.login(function (response) {
scope.fbLogin = response.status;
scope.fbAccessToken = response.authResponse.accessToken;
scope.Uid = response.authResponse.userID;
Facebook.api('/me?fields=id,name,email,picture', function (response) {
localStorage.setItem('user', JSON.stringify(response));
});
});
console.log('setting user');
user = JSON.parse(localStorage.getItem('user'));
},
fbLogout : function () {
Facebook.logout(function (response) {
});
user = null;
localStorage.removeItem('user');
},
removeAuth : function () {
Facebook.api({
method: 'Auth.revokeAuthorization'
}, function (response) {
Facebook.getLoginStatus(function (response) {
scope.fbLogin = response.status;
});
});
}
};
}]);
Here is my Controller
app.controller('IndexController', ['$scope', '$location', '$http', 'mainService', function ($scope, $location, $http, mainService) {
$scope.ms = mainService;
$scope.user = mainService.user;
$http({
method: 'GET',
url: 'backend/api/v1/getItems.php',
headers: { "Content-Type": 'text/json; charset="utf-8"' }
})
.success(function(data, status) {
//alert("status is : "+status);
if(status === 200) {
$scope.items = data;
}
})
.error(function(data, status) {
$scope.items = [];
});
}]);
Calling login function < li >< a href="#/" ng-click="ms.fbLogin()">Login using Facebook
Calling data in html {{user.name}} or {{ms.user.name}}
Well, the same problem is also with logging out.
Hey so it's hard for me to say this is the exact problem but from the looks of it everything you have so far is actually pretty good.
There's only one problem I spot and it just boils down to understanding objects are bound to variables by reference. If you're not sure what that means I would say do some research on that first since it's a fundamental part of javascript.
What seems to be the problem here is that you are setting 'user' to an empty object in your service. In your controller you are then assigning $scope.user to that same object empty.
However in your login function you are assigning user to the new JSON from the storage. First, this should also be inside the success callback, right after you set the localstorage.
I'm not familiar with that module but I'm going to assume that those are async functions. Therefore you're grabbing that local storage data before it's even been set.
Also, by setting 'user' to a new object you have updated it's value in the service but not in the controller.
Because it's bound by reference, 'user' in the service now points to a new object, while $scope.user is still pointing to that original empty object.
To solve this problem you can do two things:
Handle the callback differently so that you reassign $scope.user to the new data.
Or you can take advantage of object reference.
You can keep most of your code the same, but in your service, instead of assigning the data to 'user', assign it to a property on user.
Facebook.api('/me?fields=id,name,email,picture', function (response) {
localStorage.setItem('user', JSON.stringify(response));
user.data = response;
});
Since both the service and the controller are referencing the same object, you will have access to that new data property on $scope.user.
HTML:
<span>{{user.data.name}}</span>
I have a view within my App which does a database pull to show a user images they have previously uploaded.
The problem is that another view allows them to upload new images, but when switching back to the view of their uploaded images, they have to do a full page refresh to see their new uploads.
The question is how can I force the $http.get to run every time the view is loaded?
This is what I am trying but is not doing what I think it should:
capApp.controller('myUploadedPhotos', function ($scope, $http) {
$scope.nameFilter = "";
$http.get("/ajax/myUploadedPhotos.php", { cache: false})
.success(function(response) {
$scope.photos = response;
});
});
Is there a way to do this?
Your code looks correct so possibly the request is cached from the server? You can try appending a random string to your url to break the cache. e.g.
"/ajax/myUploadedPhotos.php" + new Date().getTime()
After thinking about it, I think you can also remove the { cache: false} because Angular also won't be able to cache the request if the timestamp changes. The old requests would just be sitting around somewhere taking up memory.
I'm not quite understand your question, but there isn't any issues with next initialization behaviour:
(function(angular) {
var capApp = angular.module('yourModule', []);
capApp.controller('myUploadedPhotos', ['$scope', '$http',
function ($scope, $http) {
$scope.nameFilter = "";
$scope.actions = angular.extend($scope.actions || {}, {
init: function () {
return $http.get("/ajax/myUploadedPhotos.php", {cache: false}).then(
function (response) {
$scope.photos = response;
}, function (reason) {
console.log('Error occured: ' + reason);
});
}
});
// You could even use it in $watch
$scope.actions.init();
}
]);
})(angular);
I'm currently learning AngularJS and similar stuff, and today I've encountered a problem (probably with async).
What I'm trying to do, is to use an Angular factory to get some data from Firebase and then use the data in a controller.
App.factory('Jobs', ['$firebaseObject', function($firebaseObject) {
var ref = new Firebase('https://myapp.firebaseio.com/Jobs');
return $firebaseObject(ref);
}]);
App.controller('JobsController', ['$scope', 'Jobs', function($scope, Jobs) {
Jobs.$bindTo($scope, 'allJobs');
console.log($scope.allJobs);
}]);
This is working pretty OK. When I put {{ allJobs | json }} in a template- it is updated after few seconds. The problem is that in the controller $scope.allJobs is returning undefined (probably because the response from Firebase arrived later than the code has been executed.
My question is, how to write it, so I can access $scope.allJobs directly in the controller?
You could do something like this:
App.factory('Jobs', ["$firebaseObject",
function($firebaseObject) {
// create a reference to the Firebase where we will store our data
return function(url){
var ref = new Firebase(url);
// this uses AngularFire to create the synchronized array
return $firebaseObject(ref);
};
}
]);
Then in your controller:
App.controller('JobsController', ['$scope', 'Jobs', function($scope, Jobs) {
$scope.allJobs = Jobs('https://myapp.firebaseio.com/Jobs');
$scope.allJobs.$loaded().then();
}]);
This is showing the $loaded method as opposed to $bindTo. As the other answers/comments mention, $bindTo may be the better way to go.
Referencing to this Firebase documentation: https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebaseobject-bindtoscope-varname
I can just do it very very simple:
App.controller('JobsController', ['$scope', 'Jobs', function($scope, Jobs) {
Jobs.$bindTo($scope, 'allJobs').then(function() {
// now I have access to $scope.allJobs when everything is downloaded from Firebase
});
}]);
I have a pretty standard app which will display news items from a remote JSON feed. So basically I have decided to poll the remote server and store the JSON in localStorage (to enable offline usage). For the moment, I have a manual page/view I must click on to update the localStorage , this works fine.
The problem is that after I use my temporary manual update page, I then go to the news page/view and it is not updated. To view the current JSON contents I must hit refresh (while still developing in the browser.)
I'm totally new to Angular and have tried to find solutions to this myself - $watch or reload: true seem to be suggested as fixes, but I cannot get them to work in my case.
Route
.state('tab.news', {
url: '/news',
reload: true,
views: {
'news-tab': {
templateUrl: 'templates/news_home.html',
controller: 'newsCtrl'
}
}
})
factory
angular.module('schoolApp.services', [])
.factory('newsService', function($q) {
var newsHeadlines =localStorage.getItem('newsHeadlines') || '{"status":"READFAIL"}'; // get news as a JSON string. if newsHeadlines not found return a JSON string with fail status
var newsHeadlinesObj = JSON.parse(newsHeadlines);// convert to an object
console.log("factory newsService ran");
return {
findAll: function() {
var deferred = $q.defer();
deferred.resolve(newsHeadlinesObj);
return deferred.promise; // or reject(reason) to throw an error in the controller https://docs.angularjs.org/api/ng/service/$q
},
findById: function(newsId) {
var deferred = $q.defer();
var newsItem = newsHeadlinesObj[newsId];
deferred.resolve(newsItem);
return deferred.promise;
}
}
});
Controller
schoolApp.controller('newsCtrl', function($scope, newsService) {
console.log ( 'newsCtrl ran' );
newsService.findAll().then(function (newsHeadlinesObj) {
$scope.newsHeadlinesObj = newsHeadlinesObj;
}, function(error){
console.log(error)
});
})
Looking at my console, the first time I read the news, the factory then controller run, but if I go to pull more data down, then go hack to news, only the controller runs, unless I refresh, then both run again.
I do not need the news view to update 'live' while still on it (but if that can be easilly done all the better) - just to pick up new data when you go back to news after being elsewhere in the app.
Thank you.
Factories return singletons and only run once. The object newsService is cached by angular. The var declarations for newsHeadlines and newsHeadlinesObj will only ever run once; meaning your promise returning methods will always resolve the promise with the same data that was retrieved when your factory was first instantiated. You should put them in a function and call it from your find methods on the singleton object.
.factory('newsService', function($q) {
function getHeadlines() {
var newsHeadlines = localStorage.getItem('newsHeadlines') || '{"status":"READFAIL"}'; // get news as a JSON string. if newsHeadlines not found return a JSON string with fail
return JSON.parse(newsHeadlines);// convert to an object
}
return {
findAll: function() {
var headlines = getHeadlines();
var deferred = $q.defer();
deferred.resolve(headlines);
return deferred.promise; // or reject(reason) to throw an error in the controller https://docs.angularjs.org/api/ng/service/$q
},
findById: function(newsId) {
var headlines = getHeadlines();
var deferred = $q.defer();
var newsItem = headlines[newsId];
deferred.resolve(newsItem);
return deferred.promise;
}
}
});
PS - I'm sure you know and are planning to do things differently later or something, but just in case you don't: Using promises here is pointless and you have no need for $q here. You could simply return the data instead of returning the promises.
I solved this withouut promises, I just used $rootScope in the factory and $scope.$on in the controller; when I change the factory, i use $rootScope.$broadcast to tell the controller that I change it.
.factory('dataFactory', ['$http', '$rootScope', function ($http, $rootScope) {
var dataFactory = {
stock: null,
getStock: getStock
}
function getStock() {
$http.get("/api/itemfarmacia/").then(function success(res) {
dataFactory.stock = res.data;
$rootScope.$broadcast('changingStock'); //Ones who listen this will see it
}, function error(err) {
console.log("Bad request");
})
}
return dataFactory;
}])
and in the controller
.controller('atencion', ["$scope", "$state", "dataFactory", function ($scope, $state, dataFactory) {
$scope.stock = dataFactory.stock; //At first is null
dataFactory.getStock(); //wherever you execute this, $scope.stock will change
$scope.$on('changingStock', function () {//Listening
$scope.stock = dataFactory.stock; //Updating $scope
})
}])