2

Let's say I have a model given by $resource. I want to maintain a cache of what has changed and not, so I can:

  • easily revert back to pristine mode (discard changes)
  • send only changed items (e.g. using PATCH)

This is discussed a bit here: Partial Updates (aka PATCH) using a $resource based service?

It is easy to extend $resource to have other methods, e.g. $patch and getDirty() or getChanged(). But for this to work, I need to catch the original fields when loaded, so I know their clean state.

How can I capture the originally loaded fields?

My intent was to have it stored somewhere on the object itself.

Also open to better ideas.

Community
  • 1
  • 1
deitch
  • 14,019
  • 14
  • 68
  • 96

1 Answers1

1

You could use two approaches here.

  1. Use the transformResponse of $resource (see docs) in order to set up your custom tracking variables on the returned object.

  2. The $pristine/$dirty tracking mechanism is already implemented in ngFormController, so you should really use it.

frapontillo
  • 10,499
  • 11
  • 43
  • 54
  • 1
    `transformResponse` is a nice idea. That works well. Dirty tracking in a form makes sense, but what I really want is to be able to call `$patch()` instead of `$save()`. Putting that in the form means I do it in the controller, which means in every controller. Since the form is tied to the underlying model, I would prefer to just do `item.patch()`. But to do that, I need to recreate pristine/dirty in the resource itself. – deitch Feb 23 '14 at 11:14
  • You can use a service that returns a "ready-to-patch" object and call it every time, if you don't want to re-implement the dirty logic. – frapontillo Feb 23 '14 at 11:17
  • that's exactly what I was trying to do, but by wrapping `$resource`. Then all I have to do is call `item.$patch()`. Can you whip up a fiddle or gist of an example of your ready-to-patch object and how it differs from my idea? Love to get a better one. – deitch Feb 23 '14 at 11:21
  • Set up a `factory` that returns your `$resource`, then add custom methods and implementations to it. See http://kirkbushell.me/angular-js-using-ng-resource-in-a-more-restful-manner/. – frapontillo Feb 23 '14 at 11:27
  • I did something very similar. My only issue is saving the pristine state on load, so that my custom `$patch()` will only send the right resources. Take a look at https://gist.github.com/deitch/9170318 – deitch Feb 23 '14 at 11:48
  • Well, you could simply clone the object when receiving it (or instantiating it) and then do recursive checks for equality on patch. – frapontillo Feb 23 '14 at 11:53
  • Oh, clone as a pristine patch makes a lot of sense. I will see if I can trap that using `transformResponse`. That should help with a `GET`. I'll need to think of something for instantiation. Actually, that is not hard, since there is no existing state. – deitch Feb 23 '14 at 11:58
  • This would be *so* much easier if they just supported this directly in ngResource – deitch Feb 23 '14 at 12:00
  • Yeah, `ngResource` is a lot like `ngRoute`, a simple module to get you started. About the tracking system, I actually did something like this for knockout.js 2 years ago or something like that: https://github.com/frapontillo/knockout-rest. – frapontillo Feb 23 '14 at 12:01
  • What a headache, just to properly support `PATCH` with updating changed fields. – deitch Feb 23 '14 at 12:02
  • This worked, although resource `interceptor` in 1.2.x+ worked even more easily. Now I need to figure out where to store the pristine data... – deitch Feb 23 '14 at 13:58
  • ... since ngResource saves everything to `POST`. – deitch Feb 23 '14 at 14:06
  • You could use transformRequest and clear the dirty information upon sending the data. – frapontillo Feb 23 '14 at 14:09
  • Feh, not so great. If you use `interceptor` (which only manages the response), it still does its usual stuff. `transformRequest`, though, comes *instead* of the usual angular handling, so you lose any JSON transformation it does. – deitch Feb 23 '14 at 15:16