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

Conditional logic

Open glennverschooren opened this issue 7 years ago • 0 comments

Hey,

I want to extend this project with conditional logic, which allow to have more complicated logic expressed and controlled with JSON schema. For the logic rules I will use the json-rules-engine.

Example: what am I trying to accomplish?

  • Listen to form data changes
  • Run rules when the form data has changed
  • Rules can change the form schema
  • Render the form with new schema

Problems? I think it creates a new subscription each time the schema has changed. https://github.com/makinacorpus/angular2-schema-form/blob/b59cf8568f446820dee301ba9d310695a751905c/src/form.component.ts#L98

Question Do you have any idea what is the best way to accomplish this?

// Template
<sf-form
    [schema]="schema"
    [model]="model"
    [actions]="actions"
    (onChange)="onChange($event)"
    (isValid)="isValidEvent($event)"
    (onErrorChange)="onErrorChangeEvent"
    (onErrorsChange)="onErrorsChangeEvent">
</sf-form>

public rules;
public schema: any;
public model: any;

private runRules;
private updateBusy: boolean = false;

constructor() {
  this.rules = [
    {
      conditions: {
        email: "empty"
      },
      event: {
        type: "required",
        params: {
          field: "password"
        },
      }
    }
  ];
  this.schema = {
    properties: {
      email: {
        type: "string",
        description: "email",
        format: "email"
      },
      password: {
        type: "string",
        description: "Password"
      },
      rememberMe: {
        type: "boolean",
        default: false,
        description: "Remember me"
      }
    },
    required: ["email", "rememberMe"],
    buttons: [{
      id: "submit",
      label: "verzenden"
    }]
  };
  this.runRules =  rulesRunner(this.schema, this.rules, Engine, actions);
}

// Listen to the onChange event
public onChange($event): void {
  const formData: any = $event.value;

  if (formData && !this.updateBusy && !equals(this.model, formData)) {
    this.updateBusy = true;
    this.runRules(formData)
      .then((conf) => {
        if (!equals(this.schema, conf.schema)) {
          this.schema = conf.schema;
          this.model = formData;
        }
        this.updateBusy = false;
      }).bind(this));
  }
}

// This function will be called after the required event was fired
function required(params: Requiredparams, schema): void {
  cont { field } = params;
  
  if (schema.properties[field] === undefined) {
    console.error("field is missing from the schema and can't be required");
  }

  const fieldIsCurrentlyRequired = ~schema.required.indexOf(field);
  if (!fieldIsCurrentlyRequired) {
    schema.required.push(field);
  }
}

kind regards,

glennverschooren avatar Oct 09 '17 12:10 glennverschooren