ngx-schema-form icon indicating copy to clipboard operation
ngx-schema-form copied to clipboard

Being able to pass variables to Custom Widgets

Open manuelarte opened this issue 7 years ago • 2 comments

Hi, I think it could be nice to make able to pass variables to Custom Widgets, I would like to have something like this: <sf-form [schema]="mySchema" [extraData]=extraData></sf-form> And then in our custom widgets, we could use that extra data to retrieve extra data needed to complete the input, or just to perform more complex validations.

manuelarte avatar Jul 08 '17 12:07 manuelarte

Why don't you just add your extraData directly in the schema?

ebrehault avatar Jul 09 '17 10:07 ebrehault

Idea of a solution

Often the JSON schema used as base for the form will be provided by a REST web-service endpoint. Therefore it doesn't always have the final structure to create a form out of it without making changes.

I would suggest to manage an extra JSON schema to describe the form. This extra JSON schema may also contain additional fields or override existing fields.. Then merging them both together will create the final schema JSON to be used within the sf-form.

Example

Lets assume you have a JSON schema for a login provided by an REST endpoint. Actually there is not type password in JSON schema, so you would need to handle this anyway.

  1. Original JSON Schema from Webservice
const orgSchema = 
{
     "type":"object",
     "properties":{
         "password":{
           "type":"string",
           "description":"Password musst match conditions...",
           "minLength":10
         },
        "name" : {
          ...
       }
     }
}
  1. Additional JSON Schema to enhance the form or provide extra data
let formSchema = 
{
     "name": "Name for your form",
     "schemaExtradata":"schemaExtradataContent"
     "properties":{
         "password":{
           "widget": "password",
           "description":"Set a password",
           "passwordFieldExtradata":"passwordFieldExtradataContent",
           "placeholder":"*****"
         },
        "name" : {
          ...
       }
     }
}

Here name, schemaExtradata, passwordFieldExtradata and placeholder are provided as extra data and description field gets overridden.

  1. Merge them together to the final JSON schema
const finalSchemaObject = mergeDeep(newSchema, newSchemaModel);

will look like

{
     "type":"object",
     "name": "Name for your form",
     "schemaExtradata":"schemaExtradataContent"
     "properties":{
         "password":{
           "type":"string",
           "minLength":10,
           "widget": "password",
           "description":"Set a password",
           "passwordFieldExtradata":"passwordFieldExtradataContent",
           "placeholder":"*****"
         },
        "name" : {
          ...
       }
     }
}

than use it

      <sf-form [(schema)]="finalSchemaObject"></sf-form>

and this is how extra data may be accessed

   let _schemaName = this.schema.name
   let _schemaExtradata = this.schema.schemaExtradata

   let _passwordFieldExtradata = this.formProperty.schema.passwordFieldExtradata
   let _placeholder = this.formProperty.schema.placeholder

Util

This simple method here may be used to merge Objects

export default function mergeDeep(target, source) {
  const output = Object.assign({}, target);
  if (isObject(target) && isObject(source)) {
    Object.keys(source).forEach(key => {
      if (isObject(source[key])) {
        if (!(key in target)) {
          Object.assign(output, {[key]: source[key]});
        } else {
          output[key] = mergeDeep(target[key], source[key]);
        }
      } else {
        Object.assign(output, {[key]: source[key]});
      }
    });
  }
  return output;
}

daniele-pecora avatar Aug 06 '17 10:08 daniele-pecora