Accessing Polymer dynamic elements - javascript

How I can access an element inside dom-if condition?
That's part of my template:
<template>
...
<template is="dom-if" if="{{_displayUserLevelBadge(level)}}">
<div class="profileUserLevelContainer">
<iron-icon id="userLevelBadge" class="icon-20" icon="chat:verified-user"></iron-icon>
<span class="profileUserLevel">{{userLevelString}}</span>
</div>
</template>
...
</template>
I need to access #userLevelBadge in Javascript like that:
Look in the ready method.
Polymer({
is: 'custom-element',
properties: {
level: {
type: String,
value: null
},
userLevelString: {
type: String,
value: ''
}
},
ready: function() {
var userLevelBadge = this.$$('#userLevelBadge'); //return undefined
},
_displayUserLevelBadge: function(){
//not including my code
//Just returning true for simplicity
return true;
}
}
But it does not work. The condition is meet, and the HTML inside dom-if is displayed, but i can't access it using this.$$(selector), as specified in the Wiki.
Fiddle: https://jsfiddle.net/Fr0z3n/sntyw50u/

Wrap the code in this.async() to give Polymer some time to stamp the template content.

Related

How to dynamically add part of an object with an arg in a vue method

Super simple question but i've never been able to solve it.
Say we have some data:
section: {
option1: true,
option2: true
}
and on a button we have:
<button #click="toggle(option1)">
How do I dynamically paste 'option1' arg into something like this:
toggle(opp){
console.log(this.section.opp)
}
Because currently it's literally looking for this.section.opp, and opp doesn't exist in the data.
Use this.section[opp] instead of this.section.opp as opp contains dynamic value and can not access directly with dot(.) notation as it is containing a different value.
Working Demo :
new Vue({
el: '#app',
data: {
section: {
option1: true,
option2: true
},
result: null
},
methods: {
toggle(opp) {
this.result = this.section[opp];
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="toggle('option1')">Click Me</button>
<p>Result: {{ result }}</p>
</div>

How to Store Data Property Value from a Specific Item in Rendered List in Vue

I'm trying create a follow button on list items in Vue. My strategy is to grab the value of a particular list item property and store it in the data object. Then use this value in a method to add it to an array in my database.
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock">+follow</button>
</div>
I'm not sure how to get the value of result.symbol "into" the button element to set the value symbol in the data object below.
<script>
export default {
data() {
return {
results: [ // this is populated by an api call
{
currency: "USD"
exchangeShortName: "NYSE"
name: "International Game Technology PLC"
stockExchange: "NYSE"
symbol: "IGT"
},
{...},
...
],
symbol: "",
};
},
followStock() {
// add this.symbol to database array
},
},
};
</script>
I'm guessing there might be an easier strategy I'm overlooking as I'm still new to Vue, so any other solution that essentially allows me to fire off the value of result.symbol from any rendered result to my database would be awesome.
You can just pass the result as a parameter to your method.
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock(result)">+follow</button>
</div>
And in your method:
methods: {
followStock(result) {
// do something with result
console.log({result});
let symbol = result.symbol;
},
}
P.S I didn't see you put your followStock() inside a methods object, but I did so in the example. https://v2.vuejs.org/v2/api/#methods
Write directly as a function call.
The vue compiler will turn followStock(result.symbol) into function(event) {followStock(result.symbol)}.
new Vue({
el: '#app',
data() {
return {
results: [
{
name: "International Game Technology PLC",
symbol: "IGT"
},
{
name: "A name",
symbol: "A symbol"
}
]
};
},
methods: {
followStock(symbol) {
console.log(symbol)
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock(result.symbol)">+follow</button>
</div>
</div>
As Nazaire mentioned you can access the results anywhere inside the child elements when using v-for.
(it works like a normal for-loop)
It's not only limited to the corresponding element (the element in which you do v-for)
<div v-for="result in results" :key="result.symbol">
{{ result.name }}
<button #click="followStock(result.symbol)">+follow</button>
</div>
followStock(symbol){
// you can now add symbol to db
}

Can an Array be passed in an element-ui el-autocomplete callback?

I tried to use the el-autocomplete tag with the simplest version: an Array returned by the callback function (JSFiddle version).
Vue.component('button-counter', {
data: function() {
return {
selectdusers: [],
user: ''
}
},
template: '<el-container> <el-container style="margin-left: 15px; width: 150px"> <el-autocomplete class="inline-input" v-model="user" :fetch-suggestions="filterUsers" placeholder="add user" #select="handleSelect" ></el-autocomplete> <el-button type="info" icon="el-icon-plus" click="addUser(user)">Add</el-button> </el-container> </el-container>',
methods: {
addUser(user) {
this.selectedUsers.push(user)
this.user = ''
},
filterUsers(user, cb) {
console.log(user)
cb(['qqq', 'zzz'])
//return this.allusers.filter(x => _.includes(x.f+x.t, user))
},
handleSelect() {}
},
})
new Vue({
el: '#components-demo'
})
#import url("//unpkg.com/element-ui#2.4.8/lib/theme-chalk/index.css");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.7/index.js"></script>
<div id="components-demo">
<button-counter></button-counter>
</div>
The suggestion box is visually empty, depite DevTools showing the expected elements in <ElAutocompleteSuggestions> → data → suggestions
For using Array instead of Object, you can use slot in autocomplete block
<el-autocomplete ...>
<template slot-scope="{ item }">
<div class="item">{{ item }}</div>
</template>
</el-autocomplete>
What needs to be passed via the callback is an Object which must have a property called value. This property holds what is displayed as the suggestion.
For the example above:
filterUsers(user, cb) {
console.log(user)
cb([{'value': 'qqq', 'whatever': 'djhjfh'}, {'value': 'zzz', 'whatever': 'uiuiiu'}])
},

How to link words in an HTML string and assign them #click method in VueJS 2?

I have a array of strings in which I want to linkify certain words like "User object", "Promise", etc like this:
var strings = ['This returns a promise containing a User Object that has the id', 'next string']
This needs to be rendered like this
<div class="wrapper">
<div class="item" v-for="str in strings" v-html="str"></div>
</div>
The problem is I want to replace words like "User object", "Promise" and bind them to a #click event that my app can handle.
So if it were rendered like I want it to be, it would be something like this (the same v-for loop above rendered manually)
<div class="wrapper">
<div class="item">This returns a promise containing a User object that has the id</div>
<div class="item">next string</div>
</div>
I tried doing this but it doesn't bind the #click event
methods: {
linkify(str) {
return str.replace(/user object/, 'User object');
}
}
Any ideas?
Here's an example of a component that takes in a string for the full message and a string for the text to replace with a link and renders a span with that message with the link text wrapped in a <a> tag:
Vue.component('linkify', {
template: '#linkify-template',
props: {
value: { type: String },
linkText: { type: String }
},
computed: {
before() {
return this.value.split(this.linkText)[0];
},
after() {
return this.value.split(this.linkText)[1];
}
}
});
new Vue({
el: '#app',
data() {
return {
message: 'This returns a promise containing a User Object that has the id',
}
},
methods: {
foo() {
console.log('clicked')
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script type="text/x-template" id="linkify-template">
<span>
{{ before }}
<a href="#" #click.prevent="$emit('click')">
<code>{{ linkText }}</code>
</a>
{{ after }}
</span>
</script>
<div id="app">
<linkify link-text="User Object" :value="message" #click="foo"></linkify>
</div>
Okay figured it out. If somebody has a better way to do it please answer too!
Vue.component('linkify', {
props: ['value', 'words'],
template: `<span :is="html"></span>`,
data() {
return {
html: Vue.compile('<span>' + this.value.replace(new RegExp('(' + this.words.join('|') + ')', 'g'), `<code>$1</code>`) + '</span>'),
}
}
});
Now all I need to do in the main app is this:
<div class="wrapper">
<div class="item" v-for="str in strings">
<linkify :value="str" :words="['user object', 'promise']" #click="help"></linkify>
</div>
</div>
Unfortunately this only works with full version of Vue (which has the compile function)

Vuejs will not render component correctly when trying to loop thru array data or v-for

<!DOCTYPE html>
<html lang="en">
<head>
<script src="js/vue.js"></script>
<meta charset="UTF-8">
<title>V-for example</title>
</head>
<body>
<script type="x/template" id="testTemplate">
<div><h1>{{name}}</h1>
<p>{{Age}}</p></div>
</script>
<div id="example">
<div id="filler">
<template v-for="person in people">
<test-component name="{{person.name}}"></test-component>
</template>
</div>
</div>
<script>
var newComponent = Vue.extend({
template: '#testTemplate',
props: ['name'],
data: function () {
return {
Age: 1010
}
}
});
Vue.component('test-component', newComponent);
new Vue({
el: '#example',
data: {
people: [{
name: 'jason',
age: 15,
complete: true
}, {
name: 'Jeremy',
age: 20,
complete: false
}]
},
ready: function () {
var divoutput = document.querySelector('#filler');
alert(divoutput.innerHTML);
len = this.$data.people.length;
for (i = 0; i < len; i += 1) {
var nameT = this.$data.people[i].name;
divoutput.innerHTML += '<test-component name="' + nameT + '"></test-component>';
}
},
});
</script>
</body> </html>
I'm trying to take all of the people in the Vue data array and inject it into a component and add it to a innerHTML of a div during the Vue.ready() function. I show that result is being injected in to the "filler" array but the components them selves are not being rendered properly. If I make a manual instance of my component it works fine.
You shouldn't try to add Vue component using innerHTML. That's managing the DOM yourself, just let Vue do that on its own. Here is a fiddle:
https://jsfiddle.net/xccjsp4b/
I changed the script template to a div because I'm not certain you can use the script tag like that (although I could be wrong). Then you just use a v-for to loop through the people and pass the relevant data as properties. If each person is going to have their own age, you want it to be a property not a data variable.
Also, use the shorthand binding of :name="person.name" rather than name="{{person.name}}". The : tells Vue to evaluate the expression.

Categories

Resources