Vaadin ComboBox Не удается прочитать свойство 'addEventListener' со значением NULL

Я пытаюсь добавить прослушиватель событий для отображения изображения, основанного на том, какой шаблон выбран в Vaadin ComboBox. Для этого я хотел бы иметь прослушиватель событий, который... Когда значение ComboBox изменено, найдите в файле JSON путь к изображению и отобразите выбранное изображение в заполнителе div.

Я еще не создал решение для этого уровня, так как у меня проблема с моим селектором запросов. Из того, что я понимаю, он не может создать переменную combobox, поэтому обработчик событий не добавляется в combobox, потому что он не существует.

Вывод ошибки при загрузке страницы:

Uncaught TypeError: Cannot read property 'addEventListener' of null

Код для проекта:

<div id="patternSelect">
            <template is="dom-bind" id="paver">
              <div class="fieldset">
                <vaadin-combo-box id="cb1" label="Pattern" class="patterns" items="[[patterns]]"></vaadin-combo-box>
                <br>
                <vaadin-combo-box id="cb2" label="Color" class="colors" items="[[colors]]"></vaadin-combo-box>
              </div>
            </template>
        </div>


<script type="text/javascript">
    $( document ).ready(function() {
            var combobox = document.querySelector('#cb1');
            combobox.addEventListener('value-changed', function(event) {
              console.log(event.detail.value);
            });

            combobox.addEventListener('selected-item-changed', function(event) {
              console.log(event.detail.value);
        });
    });
</script>

1 ответ

Решение

Поскольку поля со списком вложены в template тег:

<template is="dom-bind" id="paver">

содержимое этого шаблона недоступно до тех пор, пока он не будет активирован и, следовательно, добавлен в DOM, взгляните на это руководство.

Vaadin / Polymer будет просматривать эти шаблоны при загрузке и активировать их, поэтому, когда вы запускаете свой код, он выглядит так, как будто это действие еще не выполнено - вызывая ваше document.querySelector('#cb1') возвращать null,

Грубый обходной путь заключается в том, чтобы обернуть ваш код слушателя в тайм-аут, и все работает хорошо:

$( document ).ready(function() {
       addListenersDelayed()
    });
});

function  addListenersDelayed(){
    setTimeout( function(){
        addListeners();
    }, 1000)    
};  

function addListeners(){

    combobox.addEventListener('value-changed', function(event) {
        console.log(event.detail.value);
    });

    combobox.addEventListener('selected-item-changed', function(event) {
        console.log(event.detail.value);
    });
}

Другой способ заключается в использовании обратных вызовов Polymer для образа жизни:

// select your template
var paver = document.querySelector('#paver');

// define the ready function callback
paver.ready = function () {
    // use the async method to make sure you can access parent/siblings
    this.async(function() {
    // access sibling or parent elements here
        var combobox = document.querySelector('#cb1')

        combobox.addEventListener('value-changed', function(event) {
            console.log(event.detail.value);
        });

        combobox.addEventListener('selected-item-changed', function(event) {
            console.log(event.detail.value);
        });

    });
};

Опасность этого заключается в том, что компонент становится готовым до регистрации обратного вызова. По сути, оба метода обеспечивают доступность DOM шаблонов при выполнении кода.

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