Generic way to detect if html form is edited

后端 未结 7 1132
悲&欢浪女
悲&欢浪女 2020-11-30 18:41

I have a tabbed html form. Upon navigating from one tab to the other, the current tab\'s data is persisted (on the DB) even if there is no change to the data.

I woul

7条回答
  •  春和景丽
    2020-11-30 19:45

    Here's a polyfill method demo in native JavaScript that uses the FormData() API to detect created, updated, and deleted form entries. You can check if anything was changed using HTMLFormElement#isChanged and get an object containing the differences from a reset form using HTMLFormElement#changes (assuming they're not masked by an input name):

    Object.defineProperties(HTMLFormElement.prototype, {
      isChanged: {
        configurable: true,
        get: function isChanged () {
          'use strict'
    
          var thisData = new FormData(this)
          var that = this.cloneNode(true)
    
          // avoid masking: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset
          HTMLFormElement.prototype.reset.call(that)
    
          var thatData = new FormData(that)
    
          const theseKeys = Array.from(thisData.keys())
          const thoseKeys = Array.from(thatData.keys())
    
          if (theseKeys.length !== thoseKeys.length) {
            return true
          }
    
          const allKeys = new Set(theseKeys.concat(thoseKeys))
    
          function unequal (value, index) {
            return value !== this[index]
          }
    
          for (const key of theseKeys) {
            const theseValues = thisData.getAll(key)
            const thoseValues = thatData.getAll(key)
    
            if (theseValues.length !== thoseValues.length) {
              return true
            }
    
            if (theseValues.some(unequal, thoseValues)) {
              return true
            }
          }
    
          return false
        }
      },
      changes: {
        configurable: true,
        get: function changes () {
          'use strict'
    
          var thisData = new FormData(this)
          var that = this.cloneNode(true)
    
          // avoid masking: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset
          HTMLFormElement.prototype.reset.call(that)
    
          var thatData = new FormData(that)
    
          const theseKeys = Array.from(thisData.keys())
          const thoseKeys = Array.from(thatData.keys())
    
          const created = new FormData()
          const deleted = new FormData()
          const updated = new FormData()
    
          const allKeys = new Set(theseKeys.concat(thoseKeys))
    
          function unequal (value, index) {
            return value !== this[index]
          }
    
          for (const key of allKeys) {
            const theseValues = thisData.getAll(key)
            const thoseValues = thatData.getAll(key)
    
            const createdValues = theseValues.slice(thoseValues.length)
            const deletedValues = thoseValues.slice(theseValues.length)
    
            const minLength = Math.min(theseValues.length, thoseValues.length)
    
            const updatedValues = theseValues.slice(0, minLength).filter(unequal, thoseValues)
    
            function append (value) {
              this.append(key, value)
            }
    
            createdValues.forEach(append, created)
            deletedValues.forEach(append, deleted)
            updatedValues.forEach(append, updated)
          }
    
          return {
            created: Array.from(created),
            deleted: Array.from(deleted),
            updated: Array.from(updated)
          }
        }
      }
    })
    
    document.querySelector('[value="Check"]').addEventListener('click', function () {
      if (this.form.isChanged) {
        console.log(this.form.changes)
      } else {
        console.log('unchanged')
      }
    })

    Radio Button Choice

提交回复
热议问题