问题
As a follow up to $resource to return array of [OO] objects how to properly wrap new domain object instances from $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() shall return object with standard $save/$update methods.
Best to modify the plunker and watch traffic then "New note" button shall work correctly.
回答1:
UPDATED
Here is a way you can continue incorporate your Note
constructor into your $resource
service...
Add a new instance method to the object returned from the factory:
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;
}
This method modifies an instantiated Note
object (to remove ID and other data that doesn't need to be passed to the server when creating a new note) before merging it with the $resource
service and returning that object to the caller.
Call that method from your controller assigning its return value to a local variable. You can also modify its properties from the controller:
var note = NoteResource.getNew();
note.title = 'Eat a lot of junk food';
Call the save
method on the note
object, passing itself as the sole parameter:
note.save(note).$promise.then(function() {
$scope.notes = NoteResource.query();
$scope.newNotes = [];
});
Watch in dev tools and notice that this does result in a JSON payload being sent with the POST containing your note
properties (which your previous solution did not).
Hopefully this solution ticks off your box for enforcing a model without having to using a factory in an unintended manner.
Plunker Demo
回答2:
Posting my solution for reference:
Latest demo: http://plnkr.co/edit/AVLQItPIfoLwsgDzoBdK?p=preview
Key item to the solution is to wrap returned json objects into javascript objects with correctly 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 = [];
});
};
});
来源:https://stackoverflow.com/questions/23528451/properly-wrap-new-domain-object-instance-with-resource