Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Schema form using Aurelia

I am using Aurelia to build a dynamic form based on a json. The form is generating from a json like the following:

Schema = [{
    'key': 'Name',
    'display': 'Name',
    'type': 'text',
    'placeholder': 'Name',
    'required': true
},
{
    'key': 'IsSubscribed',
    'display': 'Subscribed to newsletter?',
    'type': 'checkbox',
    'placeholder': null,
    'required': false
}];

The model to fill the form is available via a Web API service. So, far I succeeded using the following template.

    <template>

    <section class="au-animate">
    <h2>Edit Form</h2>
    <form class="form-group">
        <div repeat.for="item of Schema" class="form-group">
            <label if.bind="item.type === 'text' || item.type === 'checkbox'" class="control-label" for.bind="item.key">${item.display}
                <input class="form-control" id.bind="item.key" placeholder.bind="item.placeholder" type.bind="item.type" value.bind="Model[item.key]" />    
            </label>
            <label if.bind="item.type === 'textarea'">${item.display}
                <textarea placeholder.bind="item.placeholder" value.bind="Model[item.key]></textarea>
            </label>
            ...
        </div>
    </form>
    </section>

    </template>

Now I am facing difficulties, when the Model contains another object as property. E.g., for the property Address I would like a input box for City.

Hence, item.key = "Address.City".

I can bind with (1) Model.Address.City or (2) Model['Address']['City'] which are not possible as the form is generating at runtime. I would like to use something like (3) Model['Address.City'], so that I can use Model[item.key] for the binding. Is there any easy syntax to achieve this?

Example of similar application in Angular Js is Angular Schema Form

Thanks in advance.

like image 436
Suman Kundu Avatar asked Mar 09 '16 09:03

Suman Kundu


1 Answers

This can be accomplished with a binding behavior that understands what to do with the keys. The end-result is the binding will function like any other binding expression.

Here's an example: https://gist.run?id=720d20b2db5adba92f62f7e665cf3b96

app.html

<template>
  <require from="./dynamic-expression-binding-behavior"></require>

  <label>
    Address 1:
    <input value.bind="model & dynamicExpression:'address.address1'">
  </label>
  <label>
    Address 2:
    <input value.bind="model & dynamicExpression:'address.address2'">
  </label>
  <label>
    City:
    <input value.bind="model & dynamicExpression:key">
  </label>
  <label>
    State:
    <input value.bind="model & dynamicExpression:'address.state'">
  </label>
  <label>
    Zip:
    <input value.bind="model & dynamicExpression:'address.zip'">
  </label>
</template>

app.js

export class App {
  model = {
    address: {
      address1: '1 Main Street',
      address2: '',
      city: 'Burlington',
      state: 'VT',
      zip: '05401'
    }
  };

  key = 'address.city';
}

dynamic-expression-binding-behavior.js

import {inject} from 'aurelia-dependency-injection';
import {Parser} from 'aurelia-binding';
import {rebaseExpression} from './expression-rebaser';

@inject(Parser)
export class DynamicExpressionBindingBehavior {
  constructor(parser) {
    this.parser = parser;
  }

  bind(binding, source, rawExpression) {
    // Parse the expression that was passed as a string argument to
    // the binding behavior.
    let expression = this.parser.parse(rawExpression);

    // Rebase the expression
    expression = rebaseExpression(expression, binding.sourceExpression);

    // Squirrel away the binding's original expression so we can restore
    // the binding to it's initial state later.
    binding.originalSourceExpression = binding.sourceExpression;

    // Replace the binding's expression.
    binding.sourceExpression = expression;
  }

  unbind(binding, source) {
    // Restore the binding to it's initial state.
    binding.sourceExpression = binding.originalSourceExpression;
    binding.originalSourceExpression = null;
  }
}
like image 77
Jeremy Danyow Avatar answered Oct 24 '22 08:10

Jeremy Danyow