Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement beforeSet callback for input elements #42

Open
KES777 opened this issue Jan 8, 2025 · 7 comments
Open

Implement beforeSet callback for input elements #42

KES777 opened this issue Jan 8, 2025 · 7 comments

Comments

@KES777
Copy link

KES777 commented Jan 8, 2025

Is your feature request related to a problem? Please describe.
I am using component like TomSelect. I leverage Ajax loading. There is no way to precreate select with all available options. Thus HTML has this and the empty options list. Later, eg. user clicked 'load' button, data comes and should be filled into form fields. The problem is that to be filled does not have options, thus FormDataJson.FromJson( ... ) do nothing with it, because it does not have corresponding option.

Describe the solution you'd like
Allow to configure FormDataJson to create if it does not exists currently, or, probably better, destroy all current and add new one.

@brainfoolong
Copy link
Owner

Hi. Thanks for the feedback. But, that's not a thing for this library. This is a typical use case for a custom select. This custom select is responsible to set selected options, when they are available. Because the app know when it's loaded and select options are available.

It should be fairly easy to recall FormDataJson on this custom select to set correct options after they are loaded.

This library does and will not support modifying select option as it has it's own big set of challanges that comes with it. Alone the fact that FormData values contains just values, not labels for select options... And so on...

@KES777
Copy link
Author

KES777 commented Jan 9, 2025

Not sure what would be the best way then... Let me provide more details what is going on.

FormDataJson allows to set data to forms. I use hierarchical feature. Data could be 2-5 or more levels deep. This is not restricted.
When data is loaded, the HTML structure is created:

{
  Company: [{
    Country: { id: 17, name: 'Ukraine' }
    Email: []
    Phones: []
    Person: {
      Address: {}
      Email: []
      more deeper...
    }
  }]
}

The HTML subforms are created from block. There is no any individual inputs.
After this FormDataJson comes into play. FormDataJson.FromJson( ... )
This is very convenient to set this bunch of inputs in one go. And it looks like nightmare to find individual <select> and additionally create options for them manually before FromDataJson.

But it looks very easy to implement and straightforward if FromDataJson will provide a callback just right before setting up values into input, eg. { beforeSet: function( element, type, value, data ) { ... } }. Here: element is the reference to HTML input; type is element type like 'select', 'radio', 'input'; value the value to setup 17, data the reference to the current data structure { id: 17, name: 'Ukraine' }.
type probably excess, but it is already detected at FormDataJson. No need to force people to redetect HTML element again at theirs code.

In this case I could easily expand/clear select's options.
I could try to implement this feature. Does it sound good?

Or do you see how it could be done simpler?

@brainfoolong
Copy link
Owner

I understand the point you are asking for your special use case. The issue is not the technical part. It is just nothing what this library should do. It's not supposed to be used to manipulate the DOM. It's a Form data to<->json library. It's not a form generation library. Manipulating DOM options is kind of form generation/manipulation.

Beside the manipulation, i see no real benefit of having a callback "beforeSet" for any other valid use case.

Your use case it is really a thing that your custom select code with the ajax/async part must handle. Offloading this things to the code where form values are being set is just wrong in case of good coding practice. The form must be ready before values are set. Nobody expect that setting form values changing the whole set of available options, as no library does this. That's usually a thing in the state of "load available options/render options/init select" rather then setting selected options.

Sorry, you can for sure fork this library and modify it for your needs, that's why open source exist. But i cannot integrate it into this library. It's just not a feature that this lib should have.

@KES777
Copy link
Author

KES777 commented Jan 9, 2025

Yes, I understand that this library task is from/to json.

I would agree with you that form must be ready before values are set. But

  1. This HTML is not rendered by backend (except once the first time).
  2. Then this is raw HTML cached somewhere by nginx and/or other proxy and reused for different values.
  3. So this form can not be ready before values are set.
  4. Values comes later via WebSocket.

If I would have a chance to precreate <option>s then there is no any reason to set values separately.

Please take into account that this is not the general <select> tag with the small static list of <option>s. This is autolookup/autocomplete component. And for this component there is now any chances to precreate its options. The value/label pair comes together and should be set together.

Lets looks deeper how this autolookup/autocomplete component works. During users input this component creates more options on the fly and nobody blames developers about that. This is expected that this type of component changing the whole set of available options.

Because of dynamic nature of labels for options for autocomplete component: the labels arrive with values. So it looks naturally to create the option(s) and set the value(s) together, at the same time.

Just try to look at it from a different side, from the side of autocomplete component and not the general <select> tag.

@KES777 KES777 changed the title Create initial option for <select> tag Implement beforeSet callback for input elements Jan 10, 2025
@KES777
Copy link
Author

KES777 commented Jan 10, 2025

I resolved my issues with only this one simple change:

--- a/src/form-data-json.js
+++ b/src/form-data-json.js
@@ -423,6 +423,9 @@ class FormDataJson {
         if (typeof newValues[objectKey] === 'undefined') {
           continue
         }
+        if( options.beforeSet ) {
+          options.beforeSet( row, newValues );
+        }
         FormDataJson.setInputValue(row, newValues[objectKey] || null, options.triggerCha>
       }
     }

How it looks in my code:

FormDataJson.fromJson( form, data, { beforeSet: function( row, data ) {
  if( row.inputType != 'select-one' ) { return }
  
  let select =  row.input.tomselect;
  row.input.options.length =  0;
  
  const value =  select.settings.valueField;
  const label =  select.settings.labelField;
  
  const newOption = new Option( data[label], data[value] );
  newOption.selected = true;
  row.input.options.add( newOption );
  
  select.sync();
}});

PS. I see now huge of possibilities which I can perform during .fromJson call.

@brainfoolong
Copy link
Owner

Sorry, i can't do that. Even if this would be a simple change, code wise. Sometimes it's hard to stay strong, but such things as this little features is was bloats software a lot over time until the point it is unmanagable.

@KES777
Copy link
Author

KES777 commented Jan 10, 2025

Yes, this is one piece of the rest of 80% :D

Actually that is sad =( but I understand your position.

Let's keep this open and see what other people say. Probably they will find other use cases we did not count.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants