angular-xeditable icon indicating copy to clipboard operation
angular-xeditable copied to clipboard

$watch of nested directive is not triggered when form's onaftersave get called

Open sinall opened this issue 6 years ago • 6 comments

I'm trying to create a duration editor which could represent "x days x hours x minutes x seconds" for a number which stores total seconds.

So the model totalSeconds is a number, and I create object duration of class Duration in the directive, then use 4 editable-text for those 4 properties.

In link method of the directive, I create scope.duration model and watch the object duration, the callback recalculates and updates the binding model totalSeconds.

When saving,

  1. duration.days gets called first
  2. form's onaftersave gets called
  3. $watch callback for duration (or duration.days) gets called

So I'm not able to save the updated totalSeconds in step 2.

Is there a way to let step 3 done before step 2?

sinall avatar Dec 02 '19 03:12 sinall

Currently I have to use $timeout with 1 second delay in onaftersave to let $watch callback run first.

sinall avatar Dec 02 '19 09:12 sinall

Maybe use onbeforesave instead? A plunker/jsfiddle might be useful as well to see what the issue is.

ckosloski avatar Dec 02 '19 15:12 ckosloski

http://jsfiddle.net/e974t8qr/3/

sinall avatar Dec 03 '19 05:12 sinall

I took a look at this and didn't see anything obvious. Using setTimeout does fix the issue

setTimeout(function () {
    alert("validatyPeriod: " + $scope.validatyPeriod + " seconds");
  }, 100);

Couldn't find anything else that worked.

ckosloski avatar Dec 03 '19 22:12 ckosloski

When you submit editable form it performs following steps:

  1. call child's onbeforesave
  2. call form's onbeforesave
  3. write data to local model (e.g. $scope.user)
  4. call form's onaftersave
  5. call child's onaftersave

I guess the problem occurs in step 3.

sinall avatar Dec 04 '19 03:12 sinall

For someone meets the same problem, here's what I'm doing now as a workaround:

link: function(scope, element, attrs) {
 	// ...
	var formElement = element.parents('form');
	var oldCallbackName = formElement.attr('onaftersave').replace('()', '');
	var oldCallback = formElement.scope()[oldCallbackName];
	formElement.scope()[oldCallbackName] = function() {
		$timeout(function() {
			oldCallback();
		}, 100);
	};
},

By using this approach, you don't need to change the form's onaftersave callback.

sinall avatar Dec 06 '19 08:12 sinall