bfj5889
bfj5889

Reputation: 31

Binding Object to Vue multi-select

I have a table with two columns(Location and Users). The location is static information but the users is a multi-select using Vue-Select. I need to shows users currently selected for a location on page load. I grab that information from a database. I also need to be able to change the selected users of a location by using a multi-select that shows all users. Example Mock

Vue Outline

<table>
    <thead>
    <tr>
        <th class="col-xs-2">Locations</th>
        <th class="col-xs-8">Users</th>
    </tr>
    </thead>
    <tbody>
        <tr v-for="(row, index) in rows" v-bind:key="index">
            <td>
              <span>{{ row.location }}</span>
            </td>
            <td>
                <v-select multiple v-model="row.users">
                <option v-for="user in allUsers" :key="user.id" :value="user.id">{{ user.name }}</option>
                </v-select>
            </td>
        </tr>
    </tbody>
</table>

Vue

var app = new Vue({
    el: '#el',
    data() {
        return {
          errors: [],
          loading: false,
          rows: this.assignments,
          allUsers: this.users
        }
    },
   props: {
     assignments: Array,
     users: Array
   },
})

Example of how rows are returned from database

    [{
    "locations":[
      { "id":1,
        "name":"SomePlace, CA",
        "users": [
          {"id":1, "name":"Person One"},
          {"id":2, "name":"Person Two"}
        ]
      },
      { "id":2,
        "name":"AnotherPlace, CA",
        "users": [
          {"id":3, "name":"Person Three"}
        ]
      }
    ]
  },
  {
    "locations":[
      { "id":1,
        "name":"SomePlace, CA",
        "users": [
          {"id":1, "name":"Person One"},
          {"id":2, "name":"Person Two"}
        ]
      },
      { "id":2,
        "name":"AnotherPlace, CA",
        "users": [
          {"id":3, "name":"Person Three"}
        ]
      }
    ]
  }]

Example of how all users are returned from database

[
    ["id":1, "name":"Person One"],
    ["id":2, "name":"Person Two"],
    ["id":3,"name":"Person Three"],
]

Upvotes: 1

Views: 2440

Answers (2)

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

I had moved the data coming via props directly to data object, since your rows property has one item which contains locations array, i looped through the first item rows[0] and i put row as the select options :options="row" and for the second column i looped through the user of the selectedLocation :

Vue.component('v-select', VueSelect.VueSelect)

var app = new Vue({
  el: '#app',
  data() {
    return {
      errors: [],
      loading: false,
      rows: [{
          "locations": [{
              "id": 1,
              "name": "SomePlace, CA",
              "users": [{
                  "id": 1,
                  "name": "Person One"
                },
                {
                  "id": 2,
                  "name": "Person Two"
                }
              ]
            },
            {
              "id": 2,
              "name": "AnotherPlace, CA",
              "users": [{
                "id": 3,
                "name": "Person Three"
              }]
            }
          ]
        },
        {
          "locations": [{
              "id": 1,
              "name": "SomePlace, CA",
              "users": [{
                  "id": 1,
                  "name": "Person One"
                },
                {
                  "id": 2,
                  "name": "Person Two"
                }
              ]
            },
            {
              "id": 2,
              "name": "AnotherPlace, CA",
              "users": [{
                "id": 3,
                "name": "Person Three"
              }]
            }
          ]
        }
      ],
      allUsers: this.users
    }
  },
  props: {
    assignments: Array,
    users: Array
  },
})
<table>
  <thead>
    <tr>
      <th class="col-xs-2">Locations</th>
      <th class="col-xs-8">Users</th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="(row, index) in rows[0].locations" v-bind:key="index">
      <td class="lead-locations">
        {{row.name}}
      </td>
      <td class="lead-users">
        <v-select multiple v-model="row.users" label="name">
        </v-select>
      </td>
    </tr>
  </tbody>
</table>

for demo check this code

Upvotes: 1

Mohamed El-Refaie
Mohamed El-Refaie

Reputation: 855

I believe that the sample data supplied to the "rows" variable are missing.

So, I will make an imaginary assumption here that you have some web servers distributed in multiple locations and you want to manage access of users.

The following is my imaginary data for "rows" variable which is close enough to your data:

[
{
    "serverID": 1,
    "serverName": "My Backend API Server",
    "locations": [
    {
        "id": 1,
        "name": "SomePlace, CA",
        "users": [
        { "id": 1, "name": "Person One" },
        { "id": 2, "name": "Person Two" }
        ]
    },
    {
        "id": 2,
        "name": "AnotherPlace, CA",
        "users": [{ "id": 3, "name": "Person Three" }]
    }
    ]
},
{
    "serverID": 1,
    "serverName": "My Frontend App Server",
    "locations": [
    {
        "id": 1,
        "name": "SomePlace, CA",
        "users": [
        { "id": 1, "name": "Person One" },
        { "id": 2, "name": "Person Two" }
        ]
    },
    {
        "id": 2,
        "name": "AnotherPlace, CA",
        "users": [{ "id": 3, "name": "Person Three" }]
    }
    ]
}
]

Now, we have to loop over the servers array first, then loop over the locations array to get some thing close to your mock as follows:

Check this pen for the implementation.

JS Code:

Vue.component('v-select', VueSelect.VueSelect)

let servers = [
    {
        "serverID": 1,
        "serverName": "My Backend API Server",
        "locations": [
        {
            "id": 1,
            "name": "SomePlace, CA",
            "users": [
            { "id": 1, "name": "Person One" },
            { "id": 2, "name": "Person Two" }
            ]
        },
        {
            "id": 2,
            "name": "AnotherPlace, CA",
            "users": [{ "id": 3, "name": "Person Three" }]
        }
        ]
    },
    {
        "serverID": 1,
        "serverName": "My Frontend App Server",
        "locations": [
        {
            "id": 1,
            "name": "SomePlace, CA",
            "users": [
            { "id": 1, "name": "Person One" },
            { "id": 2, "name": "Person Two" }
            ]
        },
        {
            "id": 2,
            "name": "AnotherPlace, CA",
            "users": [{ "id": 3, "name": "Person Three" }]
        }
        ]
    }
    ];

let users = [
    {"id":1, "name":"Person One"},
    {"id":2, "name":"Person Two"},
    {"id":3,"name":"Person Three"},
];

var app = new Vue({
    el: '#app',
    data() {
        return {
        errors: [],
        loading: false,
        selectedLocation: {},
        rows:  servers,
        allUsers: users
        }
    }
})

HTML Code:

<div id="app">
<table>
    <thead>
    <tr>
        <th class="col-xs-2">Locations</th>
        <th class="col-xs-8">Users</th>
    </tr>
    </thead>
    <tbody>
        <tr v-for="(row, index) in rows" v-bind:key="index">
            <td colspan="2">
            <b>{{ row.serverName }}</b>
            <table>
                <tr  v-for="(location, l_index) in row.locations" v-bind:key="l_index">
                    <td class="col-xs-2">{{ location.name }}</td>
                    <td class="col-xs-8">
                    <v-select multiple v-model="location.users" label="name" :options="allUsers">
                </v-select>
                    </td>
                </tr>
            </table>
            </td>

            <td class="lead-locations">
            {{ row.locations.name }}          
            </td>
            <td class="lead-users">

            </td>
        </tr>
    </tbody>
</table>
</div>

Upvotes: 1

Related Questions