I have two functions in my Controller.
showEditScreen function which actually loads a user record over
$resource.get. updateUserDetails function which should update the user.In the showEditScreen function everything is working. The user details are parsed over json and when looking at the $scope.user object functions like $get, $post, $update are present.
When looking at the same (also unmodified) object in the updateUserDetails function the object has changed and all the functions like $get, $post, $update and so on are missing.
This is a really weird behavior. Does anybody have an explanation for this?
When I use http.put i can save the object by the way.
console.log($scope.user) output in showEditScreen() function
Resource {$get: function, $save: function, $query: function, $remove: function, $delete: function…}
firstName: "Mista"
id: "d419375a-ba0b-4177-93cf-842e2c3e046e"
lastName: "BlaaahBlaaah1"
password: "bla"
roles: Array[2]
username: "blabla1"
__proto__: Resource
console.log($scope.user) in updateUserDetails() function:
Resource {id: "d419375a-ba0b-4177-93cf-842e2c3e046e", firstName: "Mista", lastName: "BlaaahBlaaah1", username: "blabla1", password: "bla"…}
firstName: "Mista"
id: "d419375a-ba0b-4177-93cf-842e2c3e046e"
lastName: "BlaaahBlaaah1"
password: "bla"
roles: Array[2]
username: "blabla1"
__proto__: Resource
When executing $scope.user.$update() in updateUserDetails() function:
POST http://localhost:8080/api/user/.json 405 (Request method 'POST' not supported) angular.js:9120
(anonymous function) angular.js:9120
sendReq angular.js:8977
$http angular.js:8768
Resource.(anonymous function) angular-resource.js:385
Resource.(anonymous function) angular-resource.js:431
UserCtrl.$scope.updateUserDetails controllers.js:37
(anonymous function) angular.js:6212
(anonymous function) angular.js:12751
Scope.$eval angular.js:7905
Scope.$apply angular.js:7985
$delegate.__proto__.$apply index.html:500
(anonymous function) angular.js:12750
(anonymous function) angular.js:1928
forEach angular.js:110
eventHandler angular.js:1927
HTML:
<div id="user_list" class="listview_list">
<div id="user_row" class="listview_row" ng-repeat="user in users">
<div id="user_username" class="listview_column"><span class="listview_fat"> {{user.username}}</span></div>
<div id="user_firstname" class="listview_column">{{user.firstName}}</div>
<div id="user_lastname" class="listview_column">{{user.lastName}}</div>
<button class="listview_row_button" ng-click="showEditScreen(user.id)">Edit</button>
</div>
</div>
<div id="user_edit" class="edit_form" ng-show="userEditScreenIsVisible">
<form name="edit_user">
<label>Username</label><br/>
<input name="username" ng-model="user.username" required/><br/>
<label>Firstname</label><br/>
<input name="firstName" ng-model="user.firstName" required/><br/>
<label>Lastname</label><br/>
<input name="lastName" ng-model="user.lastName" required/><br/>
<button class="button" ng-click="hideEditScreen()">Close</button>
<button class="button" ng-click="updateUserDetails()">Update</button>
</form>
</div>
Controller:
/*
* Controller to display and manipulate users.
*/
function UserCtrl($scope, $http, Users, User) {
// set edit screen to invisible by default
$scope.userEditScreenIsVisible = false;
// set new screen to invisible by default
$scope.userNewScreenIsVisible = false;
// display list with users
Users.query(
{}, //params
function (data) { //success
$scope.users = data.data;
},
function (data) { //failure
console.log("Error occurred while getting list of users");
});
// show edit screen if edit button is clicked
$scope.showEditScreen = function(id) {
$scope.user = User.get({userId: id});
console.log($scope.user);
$scope.userEditScreenIsVisible = true;
}
// hide edit screen if close button is clicked
$scope.hideEditScreen = function() {
$scope.userEditScreenIsVisible = false;
}
$scope.updateUserDetails = function() {
console.log($scope.user);
$scope.user.$update();
//$http.put("http://localhost:8080/api/user/" + $scope.user.id + ".json", $scope.user);
}
// show new screen if add button is clicked
$scope.showNewScreen = function() {
$scope.userNewScreenIsVisible = true;
}
}
Service:
angular.module('user.services', ['ngResource']).
factory('Users', function($resource) {
return $resource('http://localhost\\:8080/api/user/all.json', {}, {
query: {method:'GET', params:{}, isArray:false}
});
}).
factory('User', function($resource){
return $resource('http://localhost\\:8080/api/user/:userId.json', {}, {
get: {method:'GET'},
update: {method:'PUT'}
});
})
Issue solved!!!!
Service:
// User Service
angular.module('user.services', ['ngResource']).
factory('User', function($resource){
return $resource('/api/user/:userId', {userId: '@id'}, {
query: {method: 'GET', headers: [{'Content-Type': 'application/json'}, {'Accept' : 'application/json'}]},
get: {method:'GET', headers: [{'Content-Type': 'application/json'}, {'Accept' : 'application/json'}]},
update: {method:'PUT', headers: [{'Content-Type': 'application/json'}, {'Accept' : 'application/json'}]}
});
})
The first problem was solved by Vineet. Actually the functions $get, $post, $delete and so on were present. Just further down when expanding the log record in the Chrome Batarang environment.
My actual problem was that the default query method does not like file extensions at the end such as .json
If using file extensions following will happen when not parsing an Id:
But we would like to have following to display all users:
So file extensions should not be used. The Content-Type should be negotiated through the header. Then file extensions won't be necessary to determine the Content-Type.
I changed my user.service the following way:
angular.module('user.services', ['ngResource']).
factory('User', function($resource){
return $resource('http://localhost\\:8080/api/user/:userId', {userId: '@id'}, {
query: {method: 'GET', headers: [{'Content-Type': 'application/json'}, {'Accept': 'application/json'}]},
get: {method:'GET', headers: [{'Content-Type': 'application/json'}, {'Accept': 'application/json'}]},
update: {method:'PUT', headers: [{'Content-Type': 'application/json'}, {'Accept': 'application/json'}]},
create: {method:'POST', headers: [{'Content-Type': 'application/json'}, {'Accept': 'application/json'}]},
delete: {method:'DELETE', headers: [{'Content-Type': 'application/json'}, {'Accept': 'application/json'}]}
});
})
My controller looks as followed:
function UserCtrl($scope, $resource, User) {
// set edit screen to invisible by default
$scope.userModScreenIsVisible = false;
// initialize buttons as invisible
$scope.updateUserDetailsButtonIsVisible = false;
$scope.saveUserDetailsButtonIsVisible = false;
// display list with users
$scope.getList = function() {
User.query(
{}, //params
function (data) { //success
$scope.users = data.data;
},
function (data) { //failure
console.log("Error occurred while getting list of users");
});
}
$scope.getList();
// show edit screen if edit button is clicked
$scope.showEditScreen = function(id) {
$scope.user = User.get({userId: id});
$scope.updateUserDetailsButtonIsVisible = true;
$scope.userModScreenIsVisible = true;
}
// hide edit screen if close button is clicked
$scope.hideEditScreen = function() {
$scope.updateUserDetailsButtonIsVisible = false;
$scope.saveUserDetailsButtonIsVisible = false;
$scope.userModScreenIsVisible = false;
}
// update a user
$scope.updateUserDetails = function() {
$scope.user.$update();
for(var i=0;i<$scope.users.length;i++) {
if($scope.users[i].id == $scope.user.id) {
angular.extend($scope.users[i], $scope.user);
break;
}
}
console.log($scope.user);
//$scope.user = User.get({userId: $scope.user.id});
$scope.updateUserDetailsButtonIsVisible = false;
$scope.userModScreenIsVisible = false;
}
// show a new user screen
$scope.showNewScreen = function() {
$scope.user = new User();
$scope.saveUserDetailsButtonIsVisible = true;
$scope.userModScreenIsVisible = true;
}
// save a new user
$scope.saveUserDetails = function() {
$scope.user.$create();
$scope.users.push($scope.user);
$scope.saveUserDetailsButtonIsVisible = false;
$scope.userModScreenIsVisible = false;
}
// delete a user
$scope.deleteUser = function(id) {
$scope.user = User.get({userId: id});
$scope.user.$delete();
}
}
The HTML:
<div id="user_list" class="listview_list">
<div id="user_row" class="listview_row" ng-repeat="u in users">
<div id="user_username" class="listview_column"><span class="listview_fat">{{u.username}}</span></div>
<div id="user_firstname" class="listview_column">{{u.firstName}}</div>
<div id="user_lastname" class="listview_column">{{u.lastName}}</div>
<button class="listview_row_button" ng-click="deleteUser(u.id)">Delete</button>
<button class="listview_row_button" ng-click="showEditScreen(u.id)">Edit</button>
</div>
</div>
<div id="user_new" class="new_user">
<button class="new_user_button" ng-click="showNewScreen()">Add user</button>
</div>
<div id="user_mod" class="mod_form" ng-show="userModScreenIsVisible">
<form name="mod_user">
<label>Username</label><br/>
<input name="username" ng-model="user.username"/><br/>
<label>Firstname</label><br/>
<input name="firstName" ng-model="user.firstName"/><br/>
<label>Lastname</label><br/>
<input name="lastName" ng-model="user.lastName"/><br/>
<button class="button" ng-click="hideEditScreen()">Close</button>
<button class="button" ng-click="updateUserDetails()" ng-show="updateUserDetailsButtonIsVisible">Update</button>
<button class="button" ng-click="saveUserDetails()" ng-show="saveUserDetailsButtonIsVisible">Save</button>
</form>
</div>