0

I have a local JSON file containing all of my Enum key-value pairs and would like to load them into an array that I can use easily.

enum.json

{
  "AbsenceCode": {
    "E": "Excused",
    "U": "Unexcused"
  },
  "ActiveInactive": {
    "A": "Active",
    "I": "Inactive"
  },
  "AuthenticationLog": {
    "1": "Staff",
    "2": "ParentAccess",
    "3": "StudentAccess"
  },
  "YesNo": {
    "0": "Yes",
    "1": "No"
  }
}

In my Javascript code, I want to load all of the key-value pairs into an array or object that allows me to easily access them, with the end goals of (a) doing value lookup and (b) creating select boxes.

I started something like this but I'm not wrapping my mind around it correctly and also somewhat unsure of whether this should be done with an array or an object, and whether JavaScript allows the type of array necessary to do this.

// load enumData
var enumKeys = $.getJSON("enum.json", function(json) {
  var array = [];
  for (var key in json) {
    var item = json[key];
    for (var keyvalue in item) {
      var value = item[keyvalue];
    }
    array.push(parsed[key])
  }
});
// test enumData
console.log(enumKeys["YesNo"]);

// lookup value of key
console.log(enumKeys["AbsenceCode"]["U"]);

In my Aurelia template, I would want something like this:

<template>
  <select ref="absencecode">
    <option repeat.for="keyvalue of enumKeys.AbsenceCode" value="${keyvalue.key}">${keyvalue.value}</option>
  </select>
</template>

My code is "inspired" by the answers to a lot of other similar cases but I didn't find any that matched this exact scenario. Any help would be appreciated! What code should I use to load enumKeys? How do I use the loaded array/object?

LStarky
  • 2,740
  • 1
  • 17
  • 47

2 Answers2

1

You could use a Value Converter to process object. In fact, there is a nice example for that in the [Documentation, last section].

Applying above example to your case, it's even possible to process objects without any prior transformation.

Gist demo: https://gist.run/?id=4514caa6ee7d40df2f7cfe2605451a0e

I wouldn't say it’s the most optimal solution, though. You might want to transform the data somehow before passing it to repeat.for. Just showing a possibility here.

Template:

<!-- First level properties -->
<div repeat.for="mainKey of data | keys">
    <label>${mainKey}</label>

    <!-- Sublevel - Value Object properties -->
    <select>
        <option value="">---</option>
        <option repeat.for="code of data[mainKey] | keys" 
                value="${code}">${data[mainKey][code]}</option> 
    </select>        
</div>

keys value converter:

export class KeysValueConverter {
  toView(obj) {
    return Reflect.ownKeys(obj);
  }
}

Update:

But how do I target one specific item without having to iterate over all of them?

I've extended the original gist demo, you can check it out.

This would work, but it wouldn't be reusable

<label>Absence Code</label>

<select>
    <option value="">---</option>
    <option repeat.for="code of data.AbsenceCode | keys" 
            value="${code}">${data.AbsenceCode[code]}</option> 
</select>

A better way would be to create a custom element

(Note: <require> is there for demo purposes. Normally, you'd add it to globalResources.)

Organizing above template into a custom element with source and name bindable properties:

  • source: your data object
  • name: first-level property of data object (e.g. AbsenceCode)

enum-list.html

<template>

    <require from="./keys-value-converter"></require>

    <label>${name}</label>
    <select name="${name}" class="form-control">
      <option value="">---</option>
      <option repeat.for="code of source[name] | keys" value="${code}">${source[name][code]}</option> 
    </select>

</template>

You can also use name property in conjunction with aurelia-i18n to display a meaningful label. E.g. ${name | t}.

enum-list.js

import {bindable} from 'aurelia-framework';

export class EnumList {

  @bindable source;
  @bindable name;

}

Usage

Individual dropdowns:

<enum-list source.bind="data" name="AbsenceCode"></enum-list>
<enum-list source.bind="data" name="AuthenticationLog"></enum-list>

Since <enum-list> has all the data, its name property can also be changed at runtime! :)

<label>Type</label>
<select class="form-control" value.bind="selectedType"> 
  <option repeat.for="mainKey of data | keys" value="${mainKey}">${mainKey}</option> 
</select>
<br>
<enum-list source.bind="data" name.bind="selectedType"></enum-list>
Marton Sagi
  • 1,247
  • 1
  • 8
  • 10
  • This looks great and is likely to be the accepted answer. I've created the value converter. But how do I target one specific item without having to iterate over all of them? For instance, if I ONLY want to create the "ActiveInactive" select box on a given template... – LStarky Nov 07 '16 at 22:51
  • Okay, I got it to work. This was a big help and moved me in the right direction. Thanks! – LStarky Nov 07 '16 at 23:34
  • Thanks! I was updating my answer when you accepted it. :D I think you might find it useful, so I saved it. – Marton Sagi Nov 08 '16 at 00:15
  • Thanks so much! I'll check it out! – LStarky Nov 08 '16 at 02:28
0

You could use aurelia-fetch-client as described here http://aurelia.io/hub.html#/doc/article/aurelia/fetch-client/latest/http-services/2

For example:

import {HttpClient} from 'aurelia-fetch-client';

let client = new HttpClient();

client.fetch('package.json')
  .then(response => response.json())
  .then(data => {
    console.log(data.description);
  });
Fabio
  • 11,892
  • 1
  • 25
  • 41
  • My question is not related to how to actually retrieve the data but how to parse it into a usable array. – LStarky Nov 07 '16 at 14:39
  • In the above case `data` is a usable object. You just have to iterate over it – Fabio Nov 07 '16 at 14:46
  • Maybe my problem is iterating over it. I am not able to determine how. When I console.log(enumKeys), I see the object. But when I console.log(enumKeys.YesNo), I get undefined. – LStarky Nov 07 '16 at 15:27
  • Are you sure that `YesNo` exists in the json file? There is no secret in iterating over a js object http://stackoverflow.com/questions/684672/how-do-i-loop-through-or-enumerate-a-javascript-object If this is not working there is probably something wrong with your file or code – Fabio Nov 07 '16 at 18:03