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

Custom cell component with input not re-rendering on search filter #91

Closed
chringel21 opened this issue Mar 19, 2024 · 5 comments
Closed

Comments

@chringel21
Copy link

Hi @uwla

I am currently experiencing an issue where the value of input fields in custom cell components is not correctly re-rendering when filtering via search.

I've created a Codesandbox example to show what I mean.

Notice that when filtering via search, the values of the input fields in column 3 don't update or re-render. The first entry has a job of 'Recreational Therapist', but when filtering for 'Corine', it still has the value of 'Recreational Therapist'.

Is this an issue with VDT or am I doing something wrong here regarding Vue?

Thanks in advance!

@uwla
Copy link
Owner

uwla commented Mar 20, 2024

Hello, thanks for the question.

I could reproduce the behavior, but this is neither a issue with VueDataTable or VueJS. This is expected behavior due to how VueJS works under the hood and Vue was designed to work this way. Let me explain:

  • Each component has its own data, or state if you prefer. The state is internal to the component, acessed only by it.
  • Parent components pass properties to children components. The properties cannot be changed by the chidren, only by the parents.
  • If the properties are changed from the parent, the children component will be updated and re-rendered.
  • If the properties are not changed from the parent, things may not work as expected.
  • To update the properties from the children, the children must emit an event to the parent. The parent catches the emitted event and handles it, updating properties accordingly

What is happening is the following:

  • JobComponent receives data from VueDataTable
  • Input in job component is changed, which change the internal state of the component
  • JobComponent does not emit an event to VueDataTable, so VueDataTable also does not emit an event, called userEvent, which could be used by App to change the user array
  • Because the user array is not updated within App, VueDataTable's data property is the same, and the search filter is working as expected.

What you can do is something like this:

<template>
  <input type="text" :value="job" @onChange="handleChange" :placeholder="'Please enter a job'" />
</template>

<script>
export default {
  props: {
    data: {
      type: Object,
      default: () => {},
    },
  },
  computed: {
    job() {
      return this.data.job
    }
  },
  methods: {
    handleChange(e) {
      e.preventDefault();
      const value = e.target.value;
      this.$emit('userEvent', { id: this.data.id, job: value });
    }
  }
};
</script>

Then, in App:

<template>
  <vue-data-table :params="params2" @userEvent="updateUser" />
</template>
<script>
/**/
  methods: {
    updateUser(payload) {
      const { id, job } = payload
      const index = this.data.findIndex(u => u.id === id)
      if (index === -1) throw new Error ("User not found")
      const newUser =  {... this.data[index], job };
      axios.post(`/user/${id}`, newUser).then(response => {
        const updatedUser = response.data
        this.data.slice(index, 1, updatedUser)
      })
    }
  }
/**/
</script>

Please, take a look at the userEvent sections on the docs. Also, take a look at src/demo/App.ts too see how the data is updated.

If you have more questions, feel free to ask.

@Yoduh
Copy link

Yoduh commented Mar 20, 2024

@uwla I think you misunderstand the issue when you say

Input in job component is changed, which change the internal state of the component

According to the problem description, the job component input is not being changed. The only input being changed is vue-data-table's search input, which filters the table, but then does not pass the correct data prop value to the column component.

@uwla
Copy link
Owner

uwla commented Mar 21, 2024

@chringel21 and @Yoduh I think now I understand what the reported problem is, from your descriptions. But I cannot reproduce it. Look at the GIF below, which everything seems to be fine:

Issue demo

What is happening on your side? Can you show me some GIF or video?

@chringel21
Copy link
Author

Thanks @uwla for your response!

There were three things I was doing in a different was

  1. In my JobComponent I was using v-model to update the input field's value.
  2. No @onChange method on my input field.
  3. The job value was a data property, not a computed property.

After switching to :value-binding and setting the value again in the @onChange method, using event.target.value, and using a computed value, everything is working as intended.

@uwla
Copy link
Owner

uwla commented Mar 22, 2024

Good it worked!

@chringel21, I would also like to point out that the search filter only searches for normal columns by default. So, by default, if you search for "Engineer", it will display nothing instead of the rows whose job column has "Engineer" because this column uses custom component. It will only search for a column with custom component if you provide a searchFunction, which is a function that takes a row (in this case, a user) and a search query, and returns true or false if it the row should be visible:

params = {
  data: users,
  columns: [
    { key: "name" },
    { key: "email" },
    {
      key: "permissions",
      searchable: true,
      searchFunction: (search, row) => {
        search = search.toLowerCase()
        return row.permissions.some(permission =>
          permission.toLowerCase().includes(search))
      },
    }
  ]
}

@uwla uwla closed this as completed Mar 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants