1

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"],
]
bfj5889
  • 31
  • 12
  • please clarify more your use case – Boussadjra Brahim Oct 29 '18 at 18:51
  • 1
    @BoussadjraBrahim I have a table that shows a location and the users that are associated with that location. All the users that are associated to a location can be selected in the V-Select. A user is defined as an object with an id and name property. The issue is the Vue cannot support v model binding of objects. I need a workaround to be able to still use the id of user object but display the name – bfj5889 Oct 29 '18 at 20:33
  • i can't figure out your use case, could you edit this [pen](https://codepen.io/anon/pen/VENNWg?editors=1010) to give me a start point to help you – Boussadjra Brahim Oct 29 '18 at 20:38
  • 1
    Check this [pen](https://codepen.io/mrefaie/pen/YJMMbK) – Mohamed El-Refaie Oct 29 '18 at 20:55
  • @MohamedEl-Refaie You should post that as an answer with an explanation – tony19 Oct 29 '18 at 21:05
  • @bfj5889 check my answer please – Boussadjra Brahim Oct 29 '18 at 21:25
  • Thanks @tony19 but, I was not sure that I understand the question well so my pen is just considered a suggestion. – Mohamed El-Refaie Oct 29 '18 at 21:27
  • @MohamedEl-Refaie I have made a mockup to better illustrate what I mean [mockup](https://imgur.com/VHTP5EY). – bfj5889 Oct 30 '18 at 12:48
  • @BoussadjraBrahim my use case is the following. 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. – bfj5889 Oct 30 '18 at 12:51
  • So for example in the [mock] (https://imgur.com/VHTP5EY) if I click on the users for the first row I should see more users than Jackie and Adam that I can add to the select. – bfj5889 Oct 30 '18 at 12:58
  • Did you see my answer ? If so, what went wrong with it, i will improve it – Boussadjra Brahim Oct 30 '18 at 13:05

2 Answers2

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

Boussadjra Brahim
  • 82,684
  • 19
  • 144
  • 164
  • I dont know if the demo link is the correct one you meant to share but it does not compile. The other link that you shared (https://codepen.io/anon/pen/VENNWg?editors=1010) is closer. But the location should not be changeable because each location should be shown in its on row. The users dropdown should show the saved users from 'Example of how rows are returned from database' in the question with the options of 'Example of how all users are returned from database' – bfj5889 Oct 30 '18 at 13:24
  • This works perfectly! The updated pin does exactly as I needed. I was trying to bind the incorrect things to the model. Thanks for all your help @Boussadjra Brahim! – bfj5889 Oct 30 '18 at 15:14
1

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>
  • This is basically what I was trying to accomplish, but you can only select a user once. Boussadjra Brahim solution was very similar – bfj5889 Oct 30 '18 at 18:03