Как добавить EventListener в Polymer 2.0 с железными формами, загруженными iron-ajax в шаблоне dom-repeat

Я использовал следующий синтаксис для редактирования запросов железной формы перед отправкой в ​​Polymer 2.0:

connectedCallback() {
    super.connectedCallback();
    someForm.addEventListener('iron-form-presubmit, function() {...})
}

Теперь я хочу загрузить несколько железных форм внутри dom-repeat, каждый из которых имеет одну и ту же функцию iron-presubmit. Количество и содержание форм загружаются с сервера с помощью iron-ajax. Я намеревался пройтись по всем формам и добавить прослушиватель событий, но, когда я вызываю следующее, кажется, что формы еще не загружены, поэтому allForms пуста.

HTML:

<iron-ajax auto
    id="requestSchedules"
    url="/api/v2/schedules"
    handle-as="json"
    on-response="handleApiResponse"
    last-response="{{schedules}}">
</iron-ajax>

<dom-repeat items="[[schedules]]">
    <template>
      <paper-card heading="Schedule">       
        <div class="card-content">
          <iron-form id="scheduleForm[[item.id]]">
              ...

Javascript:

connectedCallback() {
    super.connectedCallback();
    var allForms = this.shadowRoot.querySelectorAll("iron-form");
    // here allForms = []
    ...
}

Проверка теневого DOM с точкой останова в этой точке показывает, что шаблон dom-repeat не загружен. Есть ли способ подождать, пока страница не загрузится, или, возможно, другой способ выполнить то же самое?

1 ответ

Решение

Вы могли бы слушать <dom-repeat> "s dom-change событие, которое происходит при изменении содержимого шаблона. Обработчик события может затем использовать querySelectorAll чтобы получить ссылку на <iron-form> s:

шаблон:

<dom-repeat on-dom-change="_onDomRepeatChange">

сценарий:

_onDomRepeatChange(e) {
  const forms = this.shadowRoot.querySelectorAll('iron-form');
  Array.from(forms).forEach(form => {
    form.addEventListener('iron-form-presubmit', function() {
      this.request.method = 'post';
      this.request.params['foo'] = true;
    });
  });
}

window.addEventListener('WebComponentsReady', () => {
  class XFoo extends Polymer.Element {
    static get is() { return 'x-foo'; }

    _onDomRepeatChange(e) {
      const forms = this.shadowRoot.querySelectorAll('iron-form');
      Array.from(forms).forEach(form => {
        form.addEventListener('iron-form-presubmit', function() {
          this.request.method = 'post';
          this.request.params['foo'] = true;
        });
        
        form.addEventListener('iron-form-response', e => {
          const response = e.detail.response;
          this.formResponse = JSON.stringify(response, null, 2);
        });
      });
    }
  }
  customElements.define(XFoo.is, XFoo);
});
<head>
  <base href="https://cdn.rawgit.com/download/polymer-cdn/2.6.0.2/lib/">
  <script src="webcomponentsjs/webcomponents-loader.js"></script>
  <link rel="import" href="polymer/polymer.html">
  <link rel="import" href="iron-ajax/iron-ajax.html">
  <link rel="import" href="iron-form/iron-form.html">
  <link rel="import" href="paper-card/paper-card.html">
</head>
<body>
  <x-foo></x-foo>

  <dom-module id="x-foo">
    <template>
      <iron-ajax auto
                 id="requestSchedules"
                 url="https://httpbin.org/anything"
                 method="POST"
                 handle-as="json"
                 content-type="application/json"
                 body='[{"id":1, "x":1},{"id":2, "x":2}]'
                 last-response="{{schedules}}">
      </iron-ajax>

      <template is="dom-repeat" items="[[schedules.json]]" on-dom-change="_onDomRepeatChange">
        <paper-card heading="Schedule">
          <div class="card-content">
            <iron-form id="scheduleForm[[item.id]]">
              <form action="https://httpbin.org/post">
                <input name="name" type="text" placeholder="Name">
                <button>Submit</button>
              </form>
            </iron-form>
          </div>
        </paper-card>
      </template>
      
      <pre>[[formResponse]]</pre>
    </template>
  </dom-module>
</body>

В качестве альтернативы вы можете использовать аннотированный прослушиватель событий на <iron-form>:

шаблон:

<iron-form on-iron-form-presubmit="_onIronFormPresubmit">

сценарий:

_onIronFormPreSubmit(e) {
  const ironForm = e.composedPath()[0];
  ironForm.request.method = 'post';
  ironForm.request.params['foo'] = true;
}

window.addEventListener('WebComponentsReady', () => {
  class XFoo extends Polymer.Element {
    static get is() { return 'x-foo'; }

    _onIronFormPreSubmit(e) {
      const ironForm = e.composedPath()[0];
      ironForm.request.method = 'post';
      ironForm.request.params['foo'] = true;
    }

    _onIronFormResponse(e) {
      const response = e.detail.response;
      this.formResponse = JSON.stringify(response, null, 2);
    }
  }
  customElements.define(XFoo.is, XFoo);
});
<head>
  <base href="https://cdn.rawgit.com/download/polymer-cdn/2.6.0.2/lib/">
  <script src="webcomponentsjs/webcomponents-loader.js"></script>
  <link rel="import" href="polymer/polymer.html">
  <link rel="import" href="iron-ajax/iron-ajax.html">
  <link rel="import" href="iron-form/iron-form.html">
  <link rel="import" href="paper-card/paper-card.html">
</head>
<body>
  <x-foo></x-foo>

  <dom-module id="x-foo">
    <template>
      <iron-ajax auto
                 id="requestSchedules"
                 url="https://httpbin.org/anything"
                 method="POST"
                 handle-as="json"
                 content-type="application/json"
                 body='[{"id":1, "x":1},{"id":2, "x":2}]'
                 last-response="{{schedules}}">
      </iron-ajax>

      <template is="dom-repeat" items="[[schedules.json]]">
        <paper-card heading="Schedule">
          <div class="card-content">
            <iron-form id="scheduleForm[[item.id]]"
                       on-iron-form-presubmit="_onIronFormPreSubmit"
                       on-iron-form-response="_onIronFormResponse">
              <form action="https://httpbin.org/post">
                <input name="name" type="text" placeholder="Name">
                <button>Submit</button>
              </form>
            </iron-form>
          </div>
        </paper-card>
      </template>
      
      <pre>[[formResponse]]</pre>
    </template>
  </dom-module>
</body>

Другие вопросы по тегам