Need to navigate to next element in an array in Polymer on button click - polymer

I have an array of objects that contain emp info like name age etc and I have a page with previous and next buttons. I want to be able to navigate to the object in the array after clicking on the next button. Do I need use something like redux to achieve this or is there another way to do this. Is there a way to do this in polymer directly.
<dom-module id="my-quiz">
<template>
<div>Employee List</div>
<button on-click="prev">Previous</button>
<button on-click="next">Next</button>
</template>
<script>
class Quiz extends Polymer.Element {
static get is() { return 'my-quiz'; }
// set this element's employees property
constructor() {
super();
this.employees = [
{ name: 'Bob', id: 'b1' },
{ name: 'Ayesha', id: 'b2' },
{ name: 'Fatma', id: 'b3' },
{ name: 'Tony', id: 'b5' }
];
}
prev() {
console.log("prev");
}
next() {
console.log("next");
}
}
window.customElements.define(Quiz.is, Quiz);
</script>
</dom-module>

Here an example how to do this. There may other ways too. :
<div>Employee ID: [[_calculateId(index)]] Name: [[_calculateName(index)]]</div>
<button on-click="prev">Previous</button>
<button on-click="next">Next</button>on>
</template>
<script>
class MyTest extends Polymer.Element {
static get is() { return 'my-test'; }
static get properties() { return {
index:{
type:Number,
value:0
}
}}
// set this element's employees property
constructor() {
super();
this.employees = [
{ name: 'Bob', id: 'b1' },
{ name: 'Ayesha', id: 'b2' },
{ name: 'Fatma', id: 'b3' },
{ name: 'Tony', id: 'b5' }
];
}
_calculateName(i) { return this.employees[i].name }
_calculateId (i) { return this.employees[i].id }
prev() {
console.log("prev");
if (this.index>0) { this.index -= 1 }
}
next() {
console.log("next");
if (this.index < this.employees.length-1){this.index +=1}
}
}
customElements.define(MyTest.is, MyTest);
Demo

Related

Vue: text field with typeahead

I want to make a text field with typeahead. I have a list of words and when you start typing them, a suggestion appears with the word(s). The thing is, it needs to be able to do it multiple times, every new word you type, it can show you a suggestion.
Anyone know how I can do this?
You can use vue-suggestion to accomplish this easily. Take a look at the demo to see if this suites you.
This is my implementation of App.vue which differs slightly.
<template>
<div>
{{ items }}
<vue-suggestion :items="results"
v-model="item"
:setLabel="setLabel"
:itemTemplate="itemTemplate"
#changed="inputChange"
#selected="itemSelected">
</vue-suggestion>
</div>
</template>
<script>
import itemTemplate from './item-template.vue';
export default {
data () {
return {
item: {},
items: [
{ id: 1, name: 'Golden Retriever'},
{ id: 2, name: 'Flying Squirrel'},
{ id: 3, name: 'Cat'},
{ id: 4, name: 'Catfish'},
{ id: 5, name: 'Squirrel'},
],
itemTemplate,
results: {}
}
},
methods: {
itemSelected (item) {
this.item = item;
},
setLabel (item) {
return item.name;
},
inputChange (text) {
// your search method
this.results = this.items.filter(item => item.name.includes(text));
// now `items` will be showed in the suggestion list
},
},
};
</script>

Why does Webcomponent object value is shared between the different instances of the same webcomponent?

I created a web component called TestElement with Polymer as below. It simply has an object value and a function which adds values to this component.
<dom-module id="test-element">
<template>Test Element</template>
<script>
class TestElement extends Polymer.Element {
static get is() { return "test-element"; }
static get properties() {
return {
_myVar: {
type: Object,
value: {},
},
};
}
addNew(key, val) {
this._myVar[key] = val;
}
}
customElements.define(TestElement.is, TestElement);
</script>
</dom-module>
I created two instances of this in a parent element as follows:
class ParentElement extends Polymer.Element {
static get is() { return "parent-element"; }
ready() {
super.ready();
this.$.myElement.addNew('key1', 'val-1');
this.$.myElement2.addNew('key2', 'val2');
console.log(this.$.myElement._myVar); // Expected to have {'key1': 'val-1'} but got {'key1': 'val-1', 'key2': 'val2'}. Why?
}
}
In the console log above, I expect to have {'key1': 'val-1'} but got {'key1': 'val-1', 'key2': 'val2'}. Why?
If you want to have a working example please refer to this plunkr:
http://plnkr.co/edit/7jSwTTBbBxD4qCbUoCGI?p=preview
JavaScript objects are by reference and when you define the default value it's a single object.
static get properties() {
return {
_myVar: {
type: Object,
value: {},
},
};
}
To avoid this you can define a function that will return a new object for each component instance.
static get properties() {
return {
_myVar: {
type: Object,
value: function() { return {}; },
},
};
}
While thinking through it I found a solution.
Test Element
class TestElement extends Polymer.Element {
static get is() { return "test-element"; }
static get properties() {
return {
_myVar: {
type: Object,
value: {},
},
};
}
ready() {
super();
_myVar = {}; // if initialized like this, the objects are not shared anymore.
}
addNew(key, val) {
this._myVar[key] = val;
}
}
customElements.define(TestElement.is, TestElement);
So below, logs what I expected:
class ParentElement extends Polymer.Element {
static get is() { return "parent-element"; }
ready() {
super.ready();
this.$.myElement.addNew('key1', 'val-1');
this.$.myElement2.addNew('key2', 'val2');
// Expected to have {'key1': 'val-1'} and got {'key1': 'val-1'} check! :)
console.log(this.$.myElement._myVar);
}
}

ReactJS: Search Bar Implementation

I want to implement a search bar in my reactJS which takes query in the search bar and show the matching assets from the API with that query till it is finished and rendering it.
import React, { Component } from 'react';
interface ApiResponse {
data: Asset[];
}
interface FetchDataExampleState
{
query: string;
assets: Asset[];
}
// The interface for our Language model.
interface Asset
{
city: string;
country: string;
lane_number: string;
location_uuid: string;
pin: string;
id: BigInt;
}
class Search extends Component<{}, FetchDataExampleState> {
constructor(props) {
super(props)
this.state = {
query: '',
assets: []
}
}
componentDidMount() {
this.serachPeople(this.state.query);
}
onChange(e) {
this.setState({ query: e.target.value }, () => {
if (this.state.query && this.state.query.length > 1) {
if (this.state.query.length % 2 === 0) {
this.serachPeople(this.state.query);
}
} else {
this.serachPeople(this.state.query);
}
})
}
serachPeople(query) {
const url = "/api/locations";
if (query) {
fetch(url, {
method: 'GET'
})
.then(response => response.json() as Promise<ApiResponse>)
.then(data => {
console.log(data.data)
// This is showing 0: {city: "bangalore", country: "india", id: 1, lane_number: "10", location_uuid: "1158", …}
//I have to search for location_uuid and show the row
}
}
render() {
return (
<form>
<input
type="text"
className="search-box"
placeholder="Search for..."
onChange={this.onChange.bind(this)}
/>
{this.state.assets}
</form>
)
}
}
export default Search;
How to render all the matching location_uuids till the last one.
Then render the keys and values of the last one. I am new to ReactJS and tried other solutions. Can anybody help me with this?

Polymer get changes from template dom-repeat

In order to get the changes from the input I use the following
<template is="dom-repeat" items="{{employees}}">
<div>First name: <input on-change="cambiado" value="{{item.first::change}}"></div>
<div>Last name: <input on-change="cambiado" value="{{item.last::change}}"></div>
</template>
...
<script>
...
cambiado(e){
var datos=this.employees[e.model.__data.index]
setTimeout(function() {
console.log(datos.first+' '+datos.last)
}, 1000);
}
...
</script>
but I am sure that Polymer can get the event in an easer way or just get the input changed. Thanks.
This the full element with the observers that does not work:
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id='employee-list'>
<template>
<div>Employee List</div>
<p></p>
<template is="dom-repeat" items="{{employees}}">
<div>First name: <input value="{{item.first}}"></div>
<div>Last name: <input value="{{item.last}}"></div>
</template>
</template>
<script>
class EmployeeList extends Polymer.Element {
static get is() { return 'employee-list' }
static get properties() {
return {
item: {
type: Object,
value: function () {
return {};
}
}
}
}
static get observers() {
return [
'itemChanged(item.*)'
]
}
constructor() {
super()
this.employees = [
{ first: 'Bob', last: 'Li' },
{ first: 'Ayesha', last: 'Johnson' },
{ first: 'Fatma', last: 'Kumari' },
{ first: 'Tony', last: 'Morelli' }
];
}
itemChanged(first) {
if (first) {
console.log('new first: ' + first);
} else {
console.log('first is undefined');
}
}
}
customElements.define(EmployeeList.is, EmployeeList)
</script>
</dom-module>
You can use observer, so when some property of the itemobject get changed named function is called:
observers: [
'itemChanged(item.*, cambiado)'
]
Docs: https://www.polymer-project.org/1.0/docs/devguide/observers

Does core Polymer 2.0 support two-way binding?

I seem to be having trouble getting two-way binding to work with Polymer 2.0. I'm keeping things minimal, only using Polymer.Element.
I define a parent component:
<dom-module id="example1a-component">
<template>
<xtal-fetch req-url="generated.json" result="{{myFetchResult}}"></xtal-fetch>
<div>fetch result:
<span>{{myFetchResult}}</span>
</div>
</template>
<script>
class Example1a extends Polymer.Element{
static get is(){return 'example1a-component'}
static get properties(){
return {
myFetchResult :{
type: String
}
}
}
}
customElements.define(Example1a.is, Example1a)
</script>
</dom-module>
The fetch class looks like:
class XtalFetch extends Polymer.Element {
static get is() { return 'xtal-fetch'; }
static get properties() {
return {
debounceTimeInMs: {
type: Number
},
reqInfo: {
type: Object,
},
reqInit: {
type: Object
},
reqUrl: {
type: String,
observer: 'loadNewUrl'
},
/**
* The expression for where to place the result.
*/
result: {
type: String,
notify: true,
readOnly: true
},
};
}
loadNewUrl() {
debugger;
}
ready() {
if (this.reqUrl) {
const _this = this;
fetch(this.reqUrl).then(resp => {
resp.text().then(txt => {
_this['_setResult'](txt);
_this['result'] = txt;
_this.notifyPath('result');
});
});
}
}
}
elements.XtalFetch = XtalFetch;
customElements.define(xtal.elements.XtalFetch.is, xtal.elements.XtalFetch);
Note that I am trying everything I can think of:
_this['_setResult'](txt);
_this['result'] = txt;
_this.notifyPath('result');
I see the result of the the fetch going into the result property of the fetch element, not into the parent.
Am I doing something wrong?
Yes, it does. Make sure to call super when you're overriding a method:
ready() {
super.ready(); // <-- important!
...
}
That's enough to make your code work (demo).
This is easy to forget, so the polymer-linter was recently updated to warn users about this.