formio / contrib

Contributed components for Form.io
18 stars 23 forks source link

[BUG] #19

Closed jiefei666 closed 8 months ago

jiefei666 commented 2 years ago

Environment

Please provide as many details as you can: Add the following code when customizing the component get className() { let name = table-responsive ${super.className} if (!this.component.bordered) { name += ' no-top-border-table' } return name } report an error: Cannot read properties of undefined (reading 'hasOwnProperty')

Steps to Reproduce

Expected behavior

Observed behavior

Example

If possible, please provide a screenshot, live example (via JSFiddle or similar), and/or example code to help demonstrate the issue.

For code or form JSON, please enclose in a code block:

// your code here
/**
 * This file shows how to create a custom component.
 *
 * c
 */
import { Components } from 'formiojs'
const FieldComponent = (Components as any).components.field
import editForm from './CheckMatrix.form'

/**
 * Here we will derive from the base component which all Form.io form components derive from.
 *
 * @param component
 * @param options
 * @param data
 * @constructor
 */
export default class CheckMatrix extends (FieldComponent as any) {
  public checks: Array<Array<any>>
  constructor(component, options, data) {
    super(component, options, data)
    this.checks = []
  }

  static schema() {
    return FieldComponent.schema({
      type: 'checkmatrix',
      numRows: 3,
      numCols: 3,
    })
  }

  public static editForm = editForm

  static builderInfo = {
    title: 'Check Matrix',
    group: 'basic',
    icon: 'fa fa-table',
    weight: 70,
    documentation: 'http://help.form.io/userguide/#table',
    schema: CheckMatrix.schema(),
  }

// 添加这 会report error
  get className() {
    let name = `table-responsive ${super.className}`
    if (!this.component.bordered) {
      name += ' no-top-border-table'
    }
    return name
  }

  get tableClass() {
    let tableClass = 'table '
    ;['striped', 'bordered', 'hover', 'condensed'].forEach((prop) => {
      if (this.component[prop]) {
        tableClass += `table-${prop} `
      }
    })
    return tableClass
  }

  renderCell(row, col) {
    return this.renderTemplate('input', {
      input: {
        type: 'input',
        ref: `${this.component.key}-${row}`,
        attr: {
          id: `${this.component.key}-${row}-${col}`,
          class: 'form-control',
          type: 'checkbox',
        },
      },
    })
  }

  public render(children) {
    return super.render(
      this.renderTemplate('checkmatrix', {
        tableClass: this.tableClass,
        renderCell: this.renderCell.bind(this),
      })
    )
  }

  /**
   * After the html string has been mounted into the dom, the dom element is returned here. Use refs to find specific
   * elements to attach functionality to.
   *
   * @param element
   * @returns {Promise}
   */
  attach(element) {
    const refs = {}

    for (let i = 0; i < this.component.numRows; i++) {
      refs[`${this.component.key}-${i}`] = 'multiple'
    }

    this.loadRefs(element, refs)

    this.checks = []
    for (let i = 0; i < this.component.numRows; i++) {
      this.checks[i] = Array.prototype.slice.call(this.refs[`${this.component.key}-${i}`], 0)

      // Attach click events to each input in the row
      this.checks[i].forEach((input) => {
        this.addEventListener(input, 'click', () => this.updateValue())
      })
    }

    // Allow basic component functionality to attach like field logic and tooltips.
    return super.attach(element)
  }

  /**
   * Get the value of the component from the dom elements.
   *
   * @returns {Array}
   */
  getValue() {
    var value = []
    for (var rowIndex in this.checks) {
      var row = this.checks[rowIndex]
      value[rowIndex] = []
      for (var colIndex in row) {
        var col = row[colIndex]
        value[rowIndex][colIndex] = !!col.checked
      }
    }
    return value
  }

  /**
   * Set the value of the component into the dom elements.
   *
   * @param value
   * @returns {boolean}
   */
  setValue(value) {
    if (!value) {
      return
    }
    for (var rowIndex in this.checks) {
      var row = this.checks[rowIndex]
      if (!value[rowIndex]) {
        break
      }
      for (var colIndex in row) {
        var col = row[colIndex]
        if (!value[rowIndex][colIndex]) {
          return false
        }
        let checked = value[rowIndex][colIndex] ? 1 : 0
        col.value = checked
        col.checked = checked
      }
    }
  }
}
daneformio commented 8 months ago

Closing this thread as it is outdated. Please re-open if it is still relevant. Thank you for your contribution!