angularjs: после ng-модели $scope.resource выглядит не так

У меня есть две функции в моем контроллере.

  • Функция showEditScreen, которая фактически загружает запись пользователя поверх $resource.get.
  • Функция updateUserDetails, которая должна обновлять пользователя.

В функции showEditScreen все работает. Сведения о пользователе анализируются в формате json, и при просмотре $scope.user объектов присутствуют такие функции, как $get, $post, $update.

При просмотре того же (также немодифицированного) объекта в функции updateUserDetails объект изменился, и все функции, такие как $get, $post, $update и т. д., отсутствуют.

Это действительно странное поведение. У кого-нибудь есть объяснение этому?

Кстати, когда я использую http.put, я могу сохранить объект.

вывод console.log($scope.user) в функции showEditScreen()

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) в функции updateUserDetails():

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

При выполнении $scope.user.$update() в функции updateUserDetails():

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 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;
}
}

Сервис:

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'}
    });
})

Проблема решена!!!!

Услуга:

// 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'}]}
    });
})

person Christopher Armstrong    schedule 09.03.2013    source источник
comment
Почему вы так уверены, что функции ресурсов не присутствуют во второй раз? console.log может обрезать строки. В Firebug см. параметр stringCropLength, который можно изменить с помощью about:config.   -  person Vineet Reynolds    schedule 09.03.2013
comment
Винит был прав, функции были доступны чуть ниже. Я удалил расширение .json и добавил заголовки типа контента. Сейчас это работает.   -  person Christopher Armstrong    schedule 10.03.2013
comment
Пожалуйста, добавьте свое решение в качестве ответа и примите его (чтобы этот вопрос больше не отображался в списке неотвеченных).   -  person Mark Rajcok    schedule 11.03.2013
comment
Готово. Должно пригодиться сейчас :)   -  person Christopher Armstrong    schedule 12.03.2013


Ответы (1)


Первую проблему решил Vineet. Собственно функции $get, $post, $delete и так далее присутствовали. Чуть ниже при расширении записи журнала в среде Chrome Batarang.

Моя реальная проблема заключалась в том, что метод запроса по умолчанию не любит расширения файлов в конце, такие как .json

При использовании расширений файлов при отсутствии анализа идентификатора произойдет следующее:

  • /api/пользователь/.json

Но мы хотели бы иметь следующее для отображения всех пользователей:

  • /апи/пользователь/

Поэтому расширения файлов не должны использоваться. Content-Type должен согласовываться через заголовок. Тогда расширения файлов не понадобятся для определения Content-Type.

Я изменил свой user.service следующим образом:

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'}]}
    });
})

Мой контроллер выглядит следующим образом:

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();
}
}

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>
person Christopher Armstrong    schedule 11.03.2013