Skip to content
This repository was archived by the owner on Dec 19, 2024. It is now read-only.
This repository was archived by the owner on Dec 19, 2024. It is now read-only.

unpleasant side-effect of bindValue default value = '' (#130) #143

@christophe-g

Description

@christophe-g

Description

While upgrading my app to Polymer 2.0, I encountered a pretty nasty side effect of #130 (bindValue having a default value = ''), where persistent data is being wiped in situation like :

<firebase-document path="/myPath" data= "{{data}}"></firebase-document>
<paper-input label="label" value="{{data.WILL_BE_DELETED}}"></paper-input>

Expected outcome

data.WILL_BE_DELETED is saved/synched between persistent layer (firebase) and paper-input.

Actual outcome

Persisted data is being wiped out because iron-input instantiate a default '' value, which is being notified to the persistent layer.

Fix

Prevent iron-input to notify upstream when the element is being attached (_initSlottedInput) and bindValue = "" (default value).

Tests are passing.

If this seems acceptable, I will propose a PR.

      _initSlottedInput: function() {
        this._isInitiatingSlottedInput = true;
        this._inputElement = this.getEffectiveChildren()[0];

        if (this.inputElement && this.inputElement.value) {
          this.bindValue = this.inputElement.value;
        }

        this._isInitiatingSlottedInput = false;
        this.fire('iron-input-ready');
      },
      
      /**
       * @suppress {checkTypes}
       */
      _bindValueChanged: function(bindValue, inputElement) {
        // The observer could have run before attached() when we have actually
        // initialized this property.
        if (!inputElement) {
          return;
        }

        if (bindValue === undefined) {
          inputElement.value = null;
        } else if (bindValue !== inputElement.value) {
          this.inputElement.value = bindValue;
        }

        if (this.autoValidate) {
          this.validate();
        }

        // Note(cg): prevent notifying the change when initiating slotted input and bindValue is default. 
        if(this._isInitiatingSlottedInput && bindValue === '') {
          return;
        }
        // manually notify because we don't want to notify until after setting value
        this.fire('bind-value-changed', {value: bindValue});
      },

Steps to reproduce

Example bellow will produce:
image

<html>
<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">

  <title>iron-input demo</title>

  <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="../../iron-demo-helpers/demo-snippet.html">
  <link rel="import" href="../../iron-demo-helpers/demo-pages-shared-styles.html">

  <link rel="import" href="../../paper-input/paper-input.html">
   <!-- Order of imports matters. The validator needs to be imported before the
    iron-input needs it. -->
  <link rel="import" href="../iron-input.html">
  
  <custom-style>
    <style is="custom-style" include="demo-pages-shared-styles"></style>
  </custom-style>
</head>
  
  <dom-module id="app-test">
    <template>
      <style>
        :host {
          display: block;
        }
        
      </style>
      <ul>
      <template is="dom-repeat" items="[[logs]]">
          <li >name: [[item]]</li>
      </template>
      </ul>
      <div >name: [[data.name]]</div>
    </template>
    <script>
      Polymer({
        is: 'app-test',
        
        properties: {
          
          data:  {
            type: Object,
            notify: true, 
            value: {}
          },

          logs: {
            type: Array, 
            value: []
          }
        },
  
        observers: ['_observeData(data, data.*)'],
        
        _observeData() {
          this.push('logs', JSON.stringify(this.data));
          if(this.data && this.data.name === '') {
            this.push('logs', 'EMPTY !!!');
          }
        }
      });
    </script>
  </dom-module>
</script>

<body>
  <div class="vertical-section-container centered">
    <h4>Basic inputs</h4>
    <demo-snippet class="">
      <template>
         <dom-bind id="app">
          <template>
            <app-test data="{{data}}"></app-test>
            <paper-input placeholder="name" label="my name" value="{{data.name}}"></paper-input>
          </template>
        </dom-bind>
      </template>
    </demo-snippet>
    <script>
    window.addEventListener('WebComponentsReady', function() {

      const app = document.querySelector('#app');
      app.data = {name:'cg'}

    });
    </script>
  </div>
</body>
</html>

Browsers Affected

  • Chrome
  • Firefox

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions