Search code examples
javascriptractivejs

Setting preselected values in multiple select with Ractive


I render a select multiple in Ractive with a computed list of all options possible, which works great. But I could not find a proper way of preselecting values.

So far I have something like:

data = [{
  type: "Person",
  Name: "John",
  worksFor: [
    "1",
    "2"
]},{
   type: "department",
   id: "1",
   Name: "Sales"
},{
   type: "department",
   id: "2",
   Name: "Marketing"
},{
   type: "department",
   id: "3",
   Name: "Accounting"
}]
new Ractive({
    el: '#list',
    template: DataTpl,
    data: {myData: data},
    computed: {
        DepartmentList () {
            //some code
            return list_of_all_Departments;
        },
        PersonsList () {
            //some Code
            return list_of_persons
        });

So in my Template I tried

{{#PersonsList}}
<select multiple>
    {{#DepartmentList}}
        <option value="{{id}}" 
            {{#if _.includes(PersonsList.worksFor, id)}} selected{{/if}}>{{Name}}
        </option>
    {{/DepartmentList}}
</select>
{{/PersonsList}}

But this just gave me a failed to compute. Does anyone know how to get those preselects?


Solution

  • This is one of the things where Ractive deviates from standards. You need to put a value attribute on <select>. The selected <option>'s value becomes <select>'s value. The kind of data you'll get from <select> depends if it's multiple or not. If it's a single-select, you get a single value. If it's multiple-select, you'll get an array.

    Setting a pre-selected value is simply the other way around. Assign a value from your data to <select>'s value and, assuming those values exist on the <option>s, they'll be selected. No template mangling required.

    Ractive.DEBUG = false;
    
    var data = [{
      type: "Person",
      Name: "John",
      worksFor: [
        "1",
        "2"
      ]
    }, {
      type: "department",
      id: "1",
      Name: "Sales"
    }, {
      type: "department",
      id: "2",
      Name: "Marketing"
    }, {
      type: "department",
      id: "3",
      Name: "Accounting"
    }];
    
    new Ractive({
      el: '#list',
      template: '#template',
      data: {
        selectedDepartments: [],
        myData: data
      },
      computed: {
        DepartmentList() {
          return this.get('myData').filter(v => v.type === 'department');
        },
        PersonsList() {
          return this.get('myData').filter(v => v.type === 'Person');
        }
      }
    });
    <script src="https://unpkg.com/ractive@0.8.11/ractive.min.js"></script>
    <div id="list"></div>
    
    <script type="template/ractive" id="template">
      {{#PersonsList}}
        {{ Name }}
      
        <select multiple value="{{ worksFor }}">
          {{#DepartmentList}}
            <option value="{{id}}">{{Name}}</option>
          {{/DepartmentList}}
        </select>
      {{/PersonsList}}
    </script>