Search code examples
ember.jsember-data

Ember JS - Add select box option to URL string via Query Param


I have a Select Box in my form and I would like to be able to use the selection as a Query Param so that I can refresh a model based on its selection. The Select Box is from this ember add-on.

{{#select-box/native value=sb name=module on-select=(action 'selected') class="form-control" as |sb| }}
          {{sb.option value='Select a Module:'}} {{sb.option value='Option1'}} {{sb.option value="Option2" }} {{sb.option value="Option3" }} {{sb.option value="option4" }}
        {{/select-box/native}}

The 'selected' action simply adds the option to a variable so that I can use it later in a switch statement:

selected(x) {
  module = x
},

I'd like to have the selection (or a representation of the selection) in my URL string but I can'tt work out how. I have other inputs building into the URL string but none of them are select boxes.

I have a 'module' item in the QueryParams on my route but it doesn't do anything, I suspect I'll have to do something in the 'selected' action but I'm not sure what.


Solution

  • I haven't used the add-on you mentioned, but here is how you can do it using normal <select>, so just bridge the gap between normal <select> and the add-on you are using in terms of making sure that the status variable in the example below changes depending on what you select in your select box - Ember will do the rest.

    Here's a configuration that works if you want to filter a list of users based on the status value you select from a dropdown:

    // app/models/user.js
    
    import DS from 'ember-data';
    
    export default DS.Model.extend({
        name: DS.attr('string'),
        status: DS.attr('string')
    });
    
    
    // app/templates/users.hbs
    
    <select onchange={{action (mut status) value="target.value"}}>
        <option value="" selected={{eq status ''}}>- All users -</option>
        <option value="active" selected={{eq status 'active'}}>Active</option>
        <option value="inactive" selected={{eq status 'inactive'}}>Inactive</option>
    </select>
    
    <ul>
        {{#each model as |user|}}
            <li>{{user.name}}, {{user.status}}</li>
        {{/each}}
    </ul>
    
    
    // app/controllers/users.js
    
    import Controller from '@ember/controller';
    
    export default Controller.extend({
        queryParams: ['status'],
        status: ''
    });
    
    
    // app/routes/users.js
    
    import Route from '@ember/routing/route';
    
    export default Route.extend({
        queryParams: {
            status: {
                refreshModel: true
            }
        },
    
        model(params) {
            var options = {};
            if (params.status) {
                options.status = params.status;
            }
            return this.get('store').query('user', options);
        }
    });
    

    How does it work?

    In the controller you define a property status, which you also indicate to be a query parameter (in the URL). Then in the route, you also define status to be a query parameter which refreshes the model. In the model() hook you extract the parameter and use it for Ember Data Store's query() to fetch the model every time you change the value of status. Your route URL will have ?status=... appended to it, and your server will receive a request similar to example.com/api/users?status=.... Of course, you can configure options in the model() hook differently to format the request URL for the server, but I kept it like this for the sake of simplicity.

    The only thing that might be confusing is the template file. Apart from the {{eq status '...'}} syntax, which is a truth helper that simply determines whether the option is selected, the rest of the selecting simply aims to change the status variable (explained in depth here).