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

[Question] - Dynamic Ops #422

Open
nathanmalishev opened this issue Oct 25, 2023 · 6 comments
Open

[Question] - Dynamic Ops #422

nathanmalishev opened this issue Oct 25, 2023 · 6 comments
Assignees
Labels
bug Something isn't working

Comments

@nathanmalishev
Copy link

nathanmalishev commented Oct 25, 2023

Summary

Hey Woylie,

Sorry for opening a ticket - I'm trying to create some dynamic ops & looking for advice.

I'm trying to achieve something like this
image

Where I have certain filters, I can further drill down.

What I have implemented works with bad / non updating elements.

I have my filter_forms

  <Flop.Phoenix.filter_fields :let={i} form={f} fields={@fields}>
      <select
      ...
      phx-change="numeric-filter"
    >
  <option
    :for={{key, label} <- [{"equal", "Is equal to"}, {"less_than", "Is less than"}]}
    value={"#{key}"}
    selected={@field.field.form.data.op == a}
  >
    <%= label %>
  </option>
</select>
<input
  id={"#{@field.field.id}_desktop"}
  name={@field.field.name}
  type="number"
  value={@field.field.value}
  field={{@field.field.form, @field.field.field}}
  {@field.rest}
/>
<./Flop.Phoenix.filter_fields>

Then my liveview I've the following/combo

  1. Keep params in assigns & update it as 'numeric-filter' is fired
  • this works to an extent but the input "#{@field.field.id}_desktop" loses it's values when switching types
  1. When initializing filter_forms, have a nurmic-filter for ops in assigns, that changes value as required
  • has similiar issues to above

Any guidance would be great thanks :)

Steps to reproduce

  1. ...

Expected behaviour

No response

Actual behaviour

No response

Elixir/Erlang version

1.15.6

Flop and Ecto versions

  • ecto 3.10.3 (Hex package) (mix)
  • ecto_sql 3.10.2 (Hex package) (mix)
    locked at 3.10.2 (ecto_sql) 68c018de
  • flop 0.23.0 (Hex package) (mix)
    locked at 0.23.0 (flop) 0521d0cb
  • flop_phoenix 0.22.2 (Hex package) (mix)
    locked at 0.22.2 (flop_phoenix) 8aa7e493

Additional context

No response

@nathanmalishev nathanmalishev added the bug Something isn't working label Oct 25, 2023
@woylie
Copy link
Owner

woylie commented Oct 25, 2023

Summary

Hey Woylie,

Sorry for opening a ticket - I'm trying to create some dynamic ops & looking for advice.

I'm trying to achieve something like this image

Where I have certain filters, I can further drill down.

What I have implemented works with bad / non updating elements.

I have my filter_forms

  <Flop.Phoenix.filter_fields :let={i} form={f} fields={@fields}>
      <select
      ...
      phx-change="numeric-filter"
    >
  <option
    :for={{key, label} <- [{"equal", "Is equal to"}, {"less_than", "Is less than"}]}
    value={"#{key}"}
    selected={@field.field.form.data.op == a}
  >
    <%= label %>
  </option>
</select>
<input
  id={"#{@field.field.id}_desktop"}
  name={@field.field.name}
  type="number"
  value={@field.field.value}
  field={{@field.field.form, @field.field.field}}
  {@field.rest}
/>
<./Flop.Phoenix.filter_fields>

I haven't implemented something like that yet. I played it bit right now, and I came this far:

<Flop.Phoenix.filter_fields :let={i} form={@form} fields={@fields} dynamic={true}>
  <.input
    label={i.label}
    type={i.type}
    field={i.field}
    {i.rest}
  />
  <.input
    label="Operator"
    type="select"
    field={Map.update!(i.field.form[:op], :id, &"#{&1}_override")}
    options={[{"equals", :==}, {"less than", :<}, {"greater than", :>}]}
  />
</Flop.Phoenix.filter_fields>

filter_fields/1 renders a hidden input for the operator. Here, a select is used to override that hidden input. The field struct derived from the form in the field struct for the value input. I appended override to the field id to prevent duplicate DOM IDs. I also added the dynamic={true} option.

This works until you type something in the text input. For some reason, the operator select resets in that case, although the parameters and the meta struct look fine.

I didn't have to implement a dynamic filter form yet, and I don't know what's going wrong here yet. I was planning to implement a demo application at some point, which would also include dynamic operators in filter forms, and completely dynamic forms. But I don't know when I'll get to that.

@nathanmalishev
Copy link
Author

Thanks @woylie for the example & insight. I'll have a play with the everything see if I can come up with anything that works, work arounds or solutions :)

@nathanmalishev
Copy link
Author

Great news @woylie I got it to work with what doesn't seem to much of a hack.

With my components and such the code is below - you fire a handle event in the form of all the events that the form fires off.

All you need to do is take the field name which looks something like filter[filters][2][value] and change it to modify the op value. So we need to fire the filter[filters][2][op] and the value associated along with that will change the handle events nicely.

everything updates on page, nothing is disappearing for me. No need to muck around with assigns, or firing events to other components etc. Seems like a very simple nice solution - at the moment. Thanks for taking the time to point me in the right direction. Also I could leave dynamic={true} out of the equation.

    <.input label={@field.label} type={@field.type} field={{@field.field.form, @field.field.field}} {@field.rest} />
    <.input
      id={Map.update!(@field.field.form, :id, &"#{&1}_override").id}
      name={String.replace(@field.field.name, "[value]", "[op]")}  <!-- Important part here ! -->
      label="Operator"
      type="select"
      errors={[]}
    >
      <:options
        :for={{key, label} <- [{"equals", :==}, {"less than", :<}, {"greater than", :>}]}
        id={"#{key}_option_#{@field.label}_desktop"}
        value={"#{label}"}
        selected={false}
      >
        <%= label %>
      </:options>
    </.input>

Cheers!

@nathanmalishev
Copy link
Author

Actually turns out there are some more issues with it.

What I have found is that @field.field.form.data <- the data in here will only update correctly if the original ops value associated with it is the same as originally passed in to the filter_form fields.

A crude but doable work around for the moment is to reach into @field.field.form.source.flop.filters and pull out the required values here. This only works to an extent - the 'op' selector can track this, but the main input will get wiped because it's still using the @field.field.form.data field.

In short -> @field.field.form.data updater should be checked to make sure the ops can be updated on a handle_event I believe?

@woylie woylie self-assigned this Oct 26, 2023
@woylie
Copy link
Owner

woylie commented Nov 11, 2023

the data in here will only update correctly if the original ops value associated with it is the same as originally passed in to the filter_form fields.

That's true, that's the current implementation. I'll get to the functionality for more dynamic filter form eventually. I don't have any advice at this point, unfortunately.

@nathanmalishev
Copy link
Author

All good - appreciate all the work so far on the lib :) it's great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants