Page MenuHomePhabricator

Fix two-way binding on the OtherKeys component
Closed, ResolvedPublic

Description

When adding another key, the addNewKey functions does this.$set( this.otherkeydata, key, ''); and at this point, the values shown in the string inputs .ext-wikilambda-zstring disappear.

This happens because the form is painted using the keys and values of the data object otherkeydata in the OtherKeys component. However, when the values of these fields are changed, the updated object is not the OtherKeys state, but that of the parent, contained in zobject. So whenever the state on which the form depends (otherkeydata) is changed, the DOM is generated again and the fields are reset to empty.

We should:

  • First, figure out the need for keeping state local to the component as otherkeydata, there might be some reason behind it.
  • Fix this behavior, whether is by keeping otherkeydata or by using the prop zobject to both capture values and print the forms. Ultimately, the user should not lose sight of the data that they have entered. in previous input fields.

Event Timeline

Oh yeah, I had noticed this was broken and wasn't sure the cause... This gives me a clue on the cause but I'm not sure how to fix. Will think a bit about it but feel free to propose a specific solution!

Change 654668 had a related patch set uploaded (by ArthurPSmith; owner: ArthurPSmith):
[mediawiki/extensions/WikiLambda@master] Prevent adding a second key with the same value as an existing key

https://gerrit.wikimedia.org/r/654668

Above change doesn't address the main question here.

However, I'm not sure now exactly how to reproduce the problem with the current vue components. Could somebody give a step-by-step problem description here? Thanks!

One fast way to reproduce the error should be:

  1. Go to the Special:CreateZObject page
  2. Write any string into the field value (Z2K2), you will see how this is reflected on the Current ZObject JSON representation below
  3. Add a new key, e.g. Z2K4
  4. When the key gets inserted, you will observe that the value of the Z2K2 field above disappears from the input, although it's value in the JSON representation below is still present.

This happens because the field elements are built using otherkeydata but the values are stored in zobject, having then two different objects representing the same structure but not being updated equally, so generating these discrepancies that can be confusing for the user.

I am confused as to why it is necessary to have these two objects, which adds more difficulty when handling the events and updating the information (we now need to keep in mind the update in N different places instead of just having one only source of truth), any clues anyone?

Thank you!

Able to reproduce now, thanks! It seems to be specific to string values? Not quite sure what's going on; as to why having two different objects representing the same structure; it's probably from the evolution of my thinking about how to do this and learning how vue works. I'll see if I can make the change as you imply, I guess using the zobject value directly?

Ok, I think the amended commit in gerrit now fixes this issue. I looked into the question of why the "otherkeydata" was used, and the problem is the way this component is designed we need something that has all the keys in zobject EXCEPT the Z1 and Z2 keys which are handled in the FullZobject component. If we decide that's unnecessary then we can look into replacing it simply with zobject in this component. Another alternative is maybe to create a computed object which is zobject minus those specific key-value pairs.

Change 654668 merged by jenkins-bot:
[mediawiki/extensions/WikiLambda@master] Prevent adding a second key with the same value as an existing key

https://gerrit.wikimedia.org/r/654668

Yes! Good one! As far as I've been able to test, the fields now keep their values when the object changes :D

ArthurPSmith claimed this task.

Marking as resolved then, thanks!