jQuery UI Widgets Forums DataTable What is the recommended way to add inline validation for jqxDataTable edits in A

This topic contains 1 reply, has 2 voices, and was last updated by  admin 2 weeks ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author

  • vitorio
    Participant

    Hi everyone, I am working on a CRM-like back-office app with DataTable.

    I am currently trying to solve this: What is the recommended way to add inline validation for jqxDataTable edits in Angular Reactive Forms before commit?

    So far, I tested with both static data and API data, but the UI behaves inconsistently after data updates.

    Is there an official pattern for this scenario?


    admin
    Keymaster

    Hi vitorio,

    // ===============================
    // jqxDataTable + Angular Reactive Forms
    // Inline validation BEFORE commit (recommended production pattern)
    // ===============================
    //
    // CORE IDEA:
    // Do NOT bind a FormControl per cell.
    // Instead:
    // 1) Use jqxDataTable edit lifecycle hooks
    // 2) Validate on "cellvaluechanging" (pre-commit gate)
    // 3) Optionally mirror row state into a Reactive FormGroup for complex rules
    // 4) Prevent commit by returning false OR calling args.cancel = true
    
    import { FormBuilder, FormGroup, Validators } from "@angular/forms";
    
    // -------------------------------
    // 1. OPTIONAL: Reactive Form per ROW (recommended for complex CRM rules)
    // -------------------------------
    rowForms: Map<string, FormGroup> = new Map();
    
    createRowForm(row: any) {
      return this.fb.group({
        name: [row.name, [Validators.required, Validators.minLength(2)]],
        email: [row.email, [Validators.required, Validators.email]],
        status: [row.status, [Validators.required]],
      });
    }
    
    // -------------------------------
    // 2. INIT TABLE EVENTS
    // -------------------------------
    ngAfterViewInit() {
      $("#table").on("cellbeginedit", (event: any) => {
        const row = event.args.row;
    
        if (!this.rowForms.has(row.id)) {
          this.rowForms.set(row.id, this.createRowForm(row));
        }
      });
    
      // 🔴 KEY HOOK: block invalid updates BEFORE they are committed
      $("#table").on("cellvaluechanging", (event: any) => {
        const args = event.args;
        const row = args.row;
    
        const form = this.rowForms.get(row.id);
        if (!form) return true;
    
        // simulate update
        const updated = {
          ...form.value,
          [args.datafield]: args.newvalue,
        };
    
        form.patchValue(updated, { emitEvent: false });
    
        // run validation
        form.updateValueAndValidity({ emitEvent: false });
    
        if (form.invalid) {
          // OPTION A: block edit
          args.cancel = true;
    
          // optional UX: show error
          console.warn("Validation failed:", form.errors);
    
          return false;
        }
    
        return true;
      });
    
      // optional: post-commit sync
      $("#table").on("cellvaluechanged", (event: any) => {
        const row = event.args.row;
        const form = this.rowForms.get(row.id);
    
        if (form?.valid) {
          this.syncToAPI(row.id, form.value);
        }
      });
    }
    
    // -------------------------------
    // 3. COLUMN-LEVEL VALIDATION (LIGHTWEIGHT OPTION)
    // -------------------------------
    // This is jqx-native and often sufficient for simple rules
    
    columns: any[] = [
      {
        text: "Email",
        datafield: "email",
        validation: (cell: any, value: string) => {
          const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    
          if (!value) {
            return { result: false, message: "Email is required" };
          }
    
          if (!emailRegex.test(value)) {
            return { result: false, message: "Invalid email format" };
          }
    
          return { result: true };
        },
      },
    ];
    
    // -------------------------------
    // 4. SAFE COMMIT PATTERN (API SYNC)
    // -------------------------------
    syncToAPI(id: string, payload: any) {
      // always re-check before sending
      const form = this.rowForms.get(id);
      if (!form || form.invalid) return;
    
      // send only validated snapshot
      this.api.updateRow(id, payload).subscribe();
    }

    Regards,
    Peter

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.