JavaScript Aurelia ValueConverter fromView confusion with multi-select aurelia value converter from view

I'm trying to use and understand the Aurelia ValueConverter in the context of a multi-select form. What I thought would be straight forward, has turned out to be a challenge for me.

I have a form to create a new deal which has multiple categories assigned to it via a multi-select input field. I've bound the output from the form into new_deal.categorizations (in the database deals have categories through categorizations).

Right now on create, through a 'brute force' method, I'm converting each category ID into a {category_id: id} object before posting to the API.

Example just logging the POST output:

  create(){
      var categorizations = this.new_deal.categorizations;
      this.new_deal.categorizations = categorizations.map(function (e) {
          return {category_id: e}
      });
      logger.debug ('POST: ', JSON.stringify(this.new_deal));
  }

Example output:

POST:  {"name":"new deal","categorizations":[{"category_id":"1"},{"category_id":"2"}]}

But I think this would better be accomplished through a ValueConverter.

Plunker is here with the full code but it's basically:

app.js:

export class App {
  constructor(){
    this.categories = [{id: 1, name: 'test1'}, {id: 2, name: 'test2'}];
    this.new_deal = {
        name:       'new deal',
        categorizations: null,
    };
  }

  create(){
      var categorizations = this.new_deal.categorizations;
      this.new_deal.categorizations = categorizations.map(function (e) {return {category_id: e}});
      logger.debug ('POST: ', JSON.stringify(this.new_deal));
  }

  create2(){
      logger.debug ('POST: ', JSON.stringify(this.new_deal));
  }

}

export class CategoryToIDValueConverter {
    fromView(id) {
        return id ? id: null;
    }
}

And app.html:

<template>
  <h1>Testing ValueConverter</h1>
   <h3 >New Brute Force Deal</h3>
     <form role="form">
       <label>Name</label>
          <input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
       <label>Categories</label>
          <select value.bind="new_deal.categorizations" multiple size="2">
              <option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
          </select>
       </form>
       <button type="submit" click.delegate="create()">Save</button>

  <h3>New ValueConverter Deal</h3>
    <form role="form">
      <label>Name</label>
          <input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
      <label>Categories</label>
          <select class="form-control" value.bind="new_deal.categorizations | categoryToID" multiple size="2">
            <option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
          </select>
    </form>
    <button class="btn btn-success" type="submit" click.delegate="create2()">Save</button>
</template>

With this I get an output of

POST:  {"name":"new deal","categorizations":["1","2"]}

In fromView in app.js, I would think I could change:

return id ? id: null;

To return an object instead of an individual value:

return id ? {category_id: id} : null

But that results in this error:

Uncaught Error: Only null or Array instances can be bound to a multi-select.

Upon further inspection, it looks like id is coming into fromView as an array...

So I modified fromView to this:

    fromView(id) {
        if(id){
          var categorizations = [];
          id.forEach(function(cat_id){
            categorizations.push({category_id: cat_id})
          });
          logger.debug(categorizations);
          logger.debug(Object.prototype.toString.call(categorizations));
          return categorizations;
        } else { return null; }
    }
}

Trying to expect an array, and then build an array of categorization objects to return, but as you can see in this Plunker, it loses the select as you click (though the debug logs show the objects being created).

Answer:1

You have an array of category objects, each having a name (string) and id (number). These will be used to populate a select element that allows multiple selection:

export class App {
  categories = [
    { id: 1, name: 'test1'},
    { id: 2, name: 'test2'}
  ];
}
<select multiple size="2">
  <option repeat.for="category of categories">${category.name}</option>
</select>

The deal object is comprised of a name (string) and categorizations. Categorization objects look like this: { category_id: 1 }

export class App {
  categories = [
    { id: 1, name: 'test1'},
    { id: 2, name: 'test2'}];

  deal = {
    name: 'new deal',
    categorizations: [],
  }
}

We want to bind the select element's value to the deal object's categorizations which is an array of objects. This means each of the select element's options need to have a object "value". An HTMLOptionElement's value attribute only accepts strings. Anything we assign to it will be coerced to a string. We can store the categorization object in a special model attribute which can handle any type. More info on this can be found in the aurelia docs.

<select multiple size="2">
  <option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>

Finally we need to bind the select element's value to the deal object's categorizations:

<select value.bind="deal.categorizations" multiple size="2">
  <option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>

All together, the view and view-model look like this:

export class App {
  categories = [
    { id: 1, name: 'test1'},
    { id: 2, name: 'test2'}];

  deal = {
    name: 'new deal',
    categorizations: [],
  }

  createDeal() {
    alert(JSON.stringify(this.deal, null, 2));
  }
}
<template>
  <form submit.delegate="createDeal()">
    <label>Name</label>
    <input type="text" placeholder="Ex. Buy One Get One Free" value.bind="deal.name">

    <label>Categories</label>
    <select value.bind="deal.categorizations" multiple size="2">
      <option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
    </select>

    <button type="submit">Save</button>
  </form>
</template>

Here's a working plunker: http://plnkr.co/edit/KO3iFBostdThrHUA0QHY?p=preview

Answer:2

If I try to use web workers through a JavaScript file, Chrome throws an error - Uncaught SecurityError: Failed to create a worker: script at '(path)/worker.js' cannot be accessed from origin 'null'...

If I try to use web workers through a JavaScript file, Chrome throws an error - Uncaught SecurityError: Failed to create a worker: script at '(path)/worker.js' cannot be accessed from origin 'null'...

  1. does chrome allow flash
  2. does chrome allow java
  3. does chrome allow javascript
  4. does chrome allow flash player
  5. does chrome allow cookies
  6. does chrome allow pop ups
  7. why does chrome allow adblock
  8. does google chrome allow cookies
  9. does google chrome allow flash
  10. does chrome support allow-from
  11. does google chrome allow java to run
  12. does google chrome allow javascript
  13. does chromecast allow amazon prime
  14. why does chrome allow pop ups
  15. chrome does not allow flash
  16. chrome does not allow download
  17. chrome does not allow camera
  18. chrome does not allow paste
  19. chrome does not allow http
  20. chrome does not allow idm extension

Yes, this question is similar with Inner function cannot access outer functions variable. But it's not the same one. What confused me is "after being changed". Codes below maybe more intuitively. var ...

Yes, this question is similar with Inner function cannot access outer functions variable. But it's not the same one. What confused me is "after being changed". Codes below maybe more intuitively. var ...

I have a kendo grid in which one column can have null values. But I don't see the grid populating when there are null values. My code is here: $(document).ready(function() { $("#grid").kendoGrid({...

I have a kendo grid in which one column can have null values. But I don't see the grid populating when there are null values. My code is here: $(document).ready(function() { $("#grid").kendoGrid({...

  1. handling null value in json
  2. handling null value in c#
  3. handling null value in sql
  4. handling null value in java
  5. handling null value for datetime c#
  6. handling null value in python
  7. handling null value in vb.net
  8. handling null value in mysql
  9. handling null value in oracle
  10. handling null value in tableau
  11. handling the null value from a resultset in java
  12. java exception handling null value
  13. null value handling json c#
  14. null value handling
  15. null value handling in db2
  16. null value handling ignore
  17. null value handling in hive
  18. null value handling in qlikview
  19. null value handling in sql server
  20. null value handling in sqoop

I am building a site with Bootstrap. On a mobile device, I have a hamburger menu. This appears as part of the Navbar. When I click the navbar, the content of the page is pushed down and the menu ...

I am building a site with Bootstrap. On a mobile device, I have a hamburger menu. This appears as part of the Navbar. When I click the navbar, the content of the page is pushed down and the menu ...

  1. bootstrap navbar horizontal align
  2. bootstrap navbar horizontal links
  3. bootstrap navbar horizontal scroll
  4. bootstrap navbar horizontal scroll mobile
  5. bootstrap navbar horizontal line
  6. bootstrap navbar horizontal to vertical
  7. bootstrap navbar horizontal
  8. bootstrap navbar horizontal list
  9. bootstrap navbar horizontal menu
  10. bootstrap navbar horizontal separator
  11. bootstrap navbar horizontal responsive
  12. bootstrap navbar horizontal center
  13. bootstrap navbar horizontal divider
  14. bootstrap navbar horizontal submenu
  15. bootstrap navbar horizontal dropdown
  16. bootstrap navbar horizontal instead of vertical
  17. bootstrap navbar horizontal collapse
  18. bootstrap horizontal navbar examples
  19. bootstrap horizontal navbar not working
  20. bootstrap 4 navbar horizontal