使用$ resource正确包装新的域对象实例

时间:2014-05-07 21:08:11

标签: angularjs angular-resource

作为$resource to return array of [OO] objects如何从$ resource

正确包装新域对象实例的后续行动
app.factory('NoteResource', ['$resource', function($resource) {

  var res = $resource('http://okigan.apiary.io/notes/:id', null, ...);

  res.newInstance = function() {
    return angular.extend(new Note(), res);
  };
}

NoteResource.newInstance()将返回带有标准$ save / $ update方法的对象。

最好修改plunker并观看traffic然后“新笔记”按钮应正常工作。

2 个答案:

答案 0 :(得分:1)

发布我的解决方案供参考:

最新演示:http://plnkr.co/edit/AVLQItPIfoLwsgDzoBdK?p=preview

解决方案的关键项是将返回的json对象包装到javascript对象中 正确 set prototype

var app = angular.module('plunker', ['ngResource']);

//
function Note() {
  this.id = '<new id>';
  this.title = '<new title>';
  this.checked = false;
  this.spellCheck = function() {
    // imagine spellchecking logic here
    this.checked = true;
  };
}

app.factory('NoteResource', function($resource) {

  var wrap = function(_) {
    // forward declaration -- function redefined below
  };

  function extend(item) {
    return angular.extend(new Note(), item);
  }

  var url = 'http://okigan.apiary.io/notes/:id';
  var res = $resource(url, null, {
    create: {
      method: 'POST',
      transformResponse: function(data, headersGetter) {
        var item = angular.fromJson(data);
        var headers = headersGetter();

        // also handle HTTP 201 response
        var extra = {
          location: headers.location
        };
        var model = wrap(item);
        angular.extend(model, extra);
        return model;
      }
    },
    query: {
      method: 'GET',
      isArray: true,
      transformResponse: function(data, headersGetter) {
        var items = angular.fromJson(data);
        var models = [];
        angular.forEach(items, function(item) {
          models.push(wrap(item));
        });
        return models;
      }
    },
    get: {
      method: 'GET',
      params: {
        id: '@id'
      },
      transformResponse: function(data, headersGetter) {
        var item = angular.fromJson(data);
        var model = wrap(item);
        return model;
      }
    }
  });

  res.url = url;

  wrap = function(data) {
    var T = Note;
    // read up on http://javascript.crockford.com/prototypal.html
    T.prototype = res.prototype;
    var instance = new T();
    angular.extend(instance, data);
    return instance;
  };

  res.newModel = function() {
    return wrap({});
  };

  return res;
});

app.controller('MainCtrl', function($scope, NoteResource) {
  $scope.name = 'World';
  $scope.notes = NoteResource.query();
  $scope.newNotes = [];

  $scope.spellCheckAllNotes = function() {
    angular.forEach($scope.notes, function(note) {
      note.spellCheck();
    });
  };

  $scope.newNote = function() {
    var note = NoteResource.newModel();
    note.title = 'Buy cheese and bread for breakfast.';
    $scope.newNotes.push(note);

    note.$save().then(function() {
      $scope.notes = NoteResource.query();
      $scope.newNotes = [];
    });

  };
});

答案 1 :(得分:1)

<强>已更新

以下是一种可以继续将Note构造函数合并到$resource服务中的方法...

为从工厂返回的对象添加新的实例方法:

res.getNew = function(){
  var newNote = new Note();
  newNote.id = undefined; // new note doesn't have id set
  newNote.checked = undefined; // don't need this data passed to server?
  angular.extend(newNote, res);
  return newNote;
}

此方法修改实例化的Note对象(在创建新笔记时删除不需要传递给服务器的ID和其他数据),然后将其与$resource合并服务并将该对象返回给调用者。

从控制器调用该方法,将其返回值分配给局部变量。您还可以从控制器修改其属性:

var note = NoteResource.getNew();
note.title = 'Eat a lot of junk food';

调用save对象上的note方法,将自身作为唯一参数传递:

note.save(note).$promise.then(function() {
  $scope.notes = NoteResource.query();
  $scope.newNotes = [];
});

在dev工具中观察并注意到这确实会导致使用包含note属性的POST(之前的解决方案没有)发送JSON有效负载。

希望这个解决方案可以帮助您执行模型,而无需以非预期的方式使用工厂。

Plunker Demo