Nilanjan Sen
Nilanjan Sen

Reputation: 19

Writable computed variables does not read value when copying same value twice

I am formatting a input into currency and using writable computed variables to update the value back to textbox.

e.g. I have a value 1234.12

I am copying the value from notepad and pasting it into the textbox, on tab out it is hitting the read function and getting formatted into currency and getting written back to textbox as $1,234. When I am pasting same value 1234, its is not hitting the read, directly getting written as it is, in to the textbox as 1234 on tab out.

I have seen this problem in js also.

Do you have any idea how to format the value if I paste the same value multiple times.

Upvotes: 1

Views: 69

Answers (1)

user3297291
user3297291

Reputation: 23372

You can use the { notify: "always" } extender to ensure your data always gets formatted.

In the example below:

  • The _backingValue contains "1234"
  • When inputing "1234" in the <input>, the computed writes "1234" to the _backingValue
  • Under normal conditions, the _backingValue would not notify any subscribers of a value change, since "1234" === "1234. However, because we explicitly told it to always trigger a valueHasMutated "event", it does notify its subscribers.
  • formattedValue's read property has a dependency on _backingValue.
  • Because _backingValue notifies us it has changed, the formatting function will run again, outputting "1234$".
  • Under normal conditions, formattedValue would not notify any subscribers of a value change, since "1234$" === "1234$". Again however, because of the extension, a valueHasMutated is triggered.
  • The <input>'s value binding receives an update and renders "1234$" to the screen.

const _backingValue = ko.observable("1234")
  .extend({ notify: "always" });

const formattedValue = ko.computed({
  read: () => _backingValue().replace(/\$/g, "") + "$",
  write: _backingValue
}).extend({ notify: "always" });


ko.applyBindings({ formattedValue });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input data-bind="value: formattedValue">

Upvotes: 0

Related Questions