I am trying to add an event listener to display an image based on which pattern is selected in the Vaadin ComboBox. To do this I would like to have an event listener that ... When the ComboBox Value is changed, then lookup in JSON file for the path to the image and display the selected image on a div placeholder.
I haven't built the solution to that level yet as I am having a problem with my query selector. From what I understand it is not able to create the variable 'combobox' and so the event handler does not get added to the 'combobox' because it doesn't exist.
The error output from loading the page is:
Uncaught TypeError: Cannot read property 'addEventListener' of null
The code for the project is:
<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>
As the combo boxes are nested within the template
tag:
<template is="dom-bind" id="paver">
the contents of this template are not accessible until it has become activated and therefore added to the DOM, take a look at this tutorial.
Vaadin/Polymer will look through these templates on load and activate them, therefore when you run your code its looks as though this action has not completed - causing your document.querySelector('#cb1')
to return null
.
A crude work around is to wrap your listener code in a timeout and everything works OK:
$( 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);
});
}
Another way is to use Polymer lifestyle callbacks:
// 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);
});
});
};
The danger with this one is that the component becomes ready before the callback is register. Essentially, both methods make sure that the DOM of the templates are available when the code is executed.