Using Aurelia to create a schema form

In my project, I am utilizing Aurelia to create a dynamic form based on a JSON data. The form is being generated from a JSON structure similar to the one shown below:

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 required to fill in the form is accessible via a Web API service. So far, I have managed to successfully implement 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>

However, I am currently encountering challenges when the Model contains another object as a property. For instance, for the Address property, I would like to include an input field specifically for City.

This leads to a scenario where item.key = "Address.City".

I am unable to bind with either (1) Model.Address.City or (2) Model['Address']['City'] since the form is dynamically generated at runtime. My aim is to use something like (3) Model['Address.City'], allowing me to utilize Model[item.key] for binding. Is there a straightforward syntax to achieve this?

An example of a similar application using Angular JS can be found at: Angular Schema Form

Thank you for any assistance provided in advance.

Answer №1

One way to achieve this is by using a binding behavior that can interpret and handle the keys appropriately. This approach will enable the binding to operate similarly to other binding expressions.

For instance, consider the following:

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 provided as a string argument for the binding behavior.
    let expression = this.parser.parse(rawExpression);

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

    // Store the original expression of the binding for future reference.
    binding.originalSourceExpression = binding.sourceExpression;

    // Set the new expression for the binding.
    binding.sourceExpression = expression;
  }

  unbind(binding, source) {
    // Restore the original state of the binding.
    binding.sourceExpression = binding.originalSourceExpression;
    binding.originalSourceExpression = null;
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using <Redirect/> in ReactJS results in rendering of a blank page

Hello everyone, I've been working on a feature where I want to redirect the user to the home page using <Redirect/> from react-router after they have successfully logged in. However, I'm facing an issue where the timeout is functioning corr ...

DiscordJS bot using Typescript experiences audio playback issues that halt after a short period of time

I am currently experiencing difficulties with playing audio through a discord bot that I created. The bot is designed to download a song from YouTube using ytdl-core and then play it, but for some reason, the song stops after a few seconds of playing. Bel ...

extract information from an external JSON document

I have a JSON file filled with data, along with a JSX file containing a button and a div. I'm looking to extract the data from the JSON file and display it in the div when the button is clicked. However, I'm at a loss on how to achieve this. The ...

When attempting to send data to the ServiceStack RESTful service, an error message of 'Access is denied' was received

I created a RESTful service using ServiceStack to send data to a database. It worked perfectly when tested locally. However, after deploying it to a server and running the same jQuery $.ajax call code, I encountered an 'Access is denied' error. I ...

Error: Module 'electron-prebuilt' not found

I am encountering an issue with my Electron app that utilizes Nightmare.js after compiling it into an .exe file using electron-packager. Everything functions properly until I click a button that triggers Nightmare.js, at which point I receive the followi ...

Tips for Implementing {{ }} within Angular Filters in Nested ng-repeat statements

I am looking to incorporate {{ }} within the Angular "filter" filter, specifically while nested inside an ng-repeat. Let's consider the relationship below: var categories = [ {"title":"land"}, {"title":"sea"}, {"title":"air"} ]; var vehi ...

Struggling to properly implement an "Errors" Object in the state function of a React Login Form Component

The issue arose while I was following a React tutorial. My objective is to develop a basic social media web application using Firebase, React, MaterialUI, and more. I am currently at around the 5:40:00 mark and have successfully resolved all previous pro ...

Tips for adjusting the default selection in a second dropdown menu

I have a dilemma with my two dropdown lists, "optionone" and "optiontwo". I am trying to alter the default selected value from "option value=3>3" to option value=3 selected>3 when the user selects 2 from the first dropdown list ("optionone"). <script&g ...

Discovering the unique identifier of an item in Node.js is simple with these steps

I have a delete API which requires the item's unique ID to be passed in for deletion. How can I capture the ID of the item being deleted and send it to the API? Here is the API: app.post("/delete_product", function (req, res) { var data = { ...

Using Angular's factory method in combination with the $http service

I am in the process of creating a factory that retrieves data from a JSON feed and returns the results. Below is the factory using $http nearestLocationApp.factory("allTheLocationsFactory", function($http){ var locations = "Not sure why it's not ...

Ways to determine if prototype methods vary

Is there a technique to verify if functions are distinct despite originating from the same prototype? I'm inquiring because I want to save functions in an array, and when attempting to delete one, it removes all functions due to sharing prototypes. ...

Unidentified googletagmanager detected in vendors segment

Recently, my ad blocker detected an unfamiliar Google Tag Manager request originating from a chunk provided by one of my vendors. Is it typical for tracking to be embedded in dependencies like this? And what type of information can be collected from my we ...

Utilizing the power of Ionic Native with AngularJS 1 for Cordova SQLite Integration

I am interested in implementing DeepLinking in my hybrid application using ionic-native. Currently, I have a functioning project with an SQLite database that has been tested on both iOS and Android platforms. However, when I include ionic.native in my app ...

Pattern matching for ' ... '

I've been struggling to make a regular expression work properly: I need it to match anything that starts with __(' or __(" and ends with ') or ") I attempted using /__\(['"][^']*['"]\)/g and /__\([&apos ...

NextJS Router delays data reloading until page receives focus

Struggling with creating an indexing page in NextJS. Attempting to retrieve the page number using the router: let router = useRouter() let page = isNaN(router.query.page) ? 1 : parseInt(router.query.page); This code is part of a React Query function withi ...

What is the best way to change CSS style for a button when clicked using JavaScript?

Is there a way to switch the background style of a CSS div when clicking the same button? function changeBg() { var divElem = document.getElementById("change-bg"); if (divElem.style.backgroundColor === "yellow") { divElem.style.backgroundColor ...

The Sizzle.js error, "Uncaught TypeError: undefined (reading 'expr')," is causing some trouble

$.expr[':'].containsCaseInsensitive = function (n, i, m) { return jQuery(n).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0; }; .expr is not recognized. To ensure it's defined, I included a CDN link below: <script src=&qu ...

The Javascript function will only initiate upon a manual reload of the page

My function is working perfectly, but only after I reload the page once it has been loaded. This function is a timer that starts counting down from 10 to 0 as soon as the page loads (which is the intended behavior). However, when I first land on the page ...

Using Sequelize to update all values in a JSON file through an Express router.put operation

I've been working on a feature in my Express router that updates data in a MySQL schema for 'members' of clubs. The members table has various columns like member_id, forename, surname, address, etc. I've successfully created an Express ...

Vue js is throwing an error because it is unable to find the "buscador" property or method that is being referenced in the render function

I am currently diving into the world of laravel combined with Vue js. I am working on integrating a search engine using vue js components, and I would greatly appreciate any help you can provide. Thank you in advance. Below is the Vue js component where t ...