I have an AngularJS
application where I have a series of text input elements that are data bound to an underlying model with the ng-model
directive:
<input type="text" myCustomDirective ng-model="cell.val" ng-model-options="{ updateOn: 'blur' }">
As you can see, I've also have custom directive on the input (myCustomDirective
), the directive includes a parser
used to process the text typed by the user and convert it to the underlying model value (and vice-versa, it also includes a formatter
to format the model value to text).
This all works correctly. However, I have a requirement to implement a custom paste function that comes into play if the user pastes some data into the input. When that happens, I need to analyze the pasted data and depending on the result I might need to alter the data being pasted or even paste some data in another text input.
To achieve this, I've added an ng-paste
directive like this:
<input type="text" myCustomDirective ng-model="cell.val" ng-model-options="{ updateOn: 'blur' }"
ng-paste="contentPasted($event)">
Inside the handler, I do my processing and then if needed I "manually paste" data in the text inputs I want by doing this:
pasteEvent.preventDefault();
setTimeout(() => inputElement.focus(), 0);
setTimeout(() => inputElement.value = myData);
setTimeout(() => inputElement.blur(), 0);
The calls to focus
and blur
are my attempt to trigger the AngularJS model update... however, this doesn't work. The value in the text input changes correctly (and is also properly processed by the myCustomDirective
formatters). But the underlying model does not update, and if I add a ng-changed
directive to the element I see that it is not being called.
NOTE: you might ask why I don't just change the value in the model and let AngularJS update the inputs. The answer is: because I want the pasted text to be processed by the parsers implemented by the myCustomDirective
directive, so I would like to simulate a "proper" paste into the textbox.
CodePudding user response:
Ok, shortly after writing the question I've found a workaround from another thread here on SO. Basically if I do this:
pasteEvent.preventDefault();
setTimeout(() => inputElement.focus(), 0);
setTimeout(() => inputElement.value = myData);
setTimeout(() => angular.element(inputElement).triggerHandler('input'));
setTimeout(() => inputElement.blur(), 0);
it works perfectly.
I'll leave the question open for a while in case someone has a cleaner / more "proper" solution.