how to change head meta data when switch the language in VUE? - javascript

is there anyone ask that question yet ? if yes, please give me the link to read this question, if not, how to do that ?
I want to change the head tittle and description each user switch the language , how can I do that ?? I do love to get some help, I am. a beginner for this :D
i have gallery.vue
i am using nuxt js here
and using nuxt-i18n
based vue-i18n
<template lang="html">
<div class="">
<p> {{ $t('post') }}</p>
</div>
</template>
<script>
export default {
head () {
return {
tittle: // how to change tittle here for the spesific languange
}
}
}
</script>
<style lang="css">
</style>
i want the result like
when in english the head tittle to be Gallery
and when user switch the italianq , the head will be the Galleria

This maybe a bit late but to help new comers.
As per documentation you may use function to set meta data so with function you access data and computed (including this), check the code:
head() {
return {
title: this.$t('myTitle'),
htmlAttrs: {
lang: this.$i18n.locale,
},
meta: [
{
hid: 'description',
name: 'description',
content: this.$t('myDescription'),
},
],
}
},
source: https://nuxtjs.org/docs/2.x/features/meta-tags-seo#local-settings

Look for vue-meta library. I'm using it for this purposes. In App.vue:
<script>
export default {
name: 'App',
metaInfo () {
return {
htmlAttrs: {
lang: this.$i18n.locale
},
...
}
},
data () {
...
}
</script>

i got it
just add head function and return the tittle: this.$i18n.messages[this.$i18n.locale].yourPropHere

Related

Filtering a stack trace array in vuejs

I am looking for some good ideas on how to filter an array that contains a stack trace. I have a database table that has four columns, one with the stack trace error messages, one that shows the priority of the error, one that shows the date the error was registered and finally a column that displays an custom made error message, which I have placed on multiple try-blocks around my system.
On the frontend I am fetching the data with axios and placing it inside an object called errors. Then in my computed properties I create an array of fields that contain the individual columns from the database and their data. I use the Bootstrap table to output it.
<template>
<b-container>
<b-card class="mt-4">
<h5>{{ $t('events') }}</h5>
<b-table
:items="errors"
:fields="fields"
:per-page="[5, 10]"
sort-desc
primary-key="id"
/>
</b-card>
</b-container>
</template>
<script>
import {errorService} from '#/services/error';
import moment from 'moment';
export default {
components: {
CommonTable,
flapper
},
data() {
return {
errors: null,
};
},
computed: {
fields() {
return [
{
key: 'priority',
label: this.$t('errorLogs.priority'),
sortable: true
},
{
key: 'creationDateTime',
label: this.$t('creationDateTime'),
formatter: date => moment(date).locale(this.$i18n.locale).format('L'),
sortable: true
},
{
key: 'stackTrace',
label: this.$t('errorLogs.stackTrace'),
sortable: true
},
{
key: 'errorMessage',
label: this.$t('message'),
sortable: true
},
]
},
},
methods: {
load(){
errorService.getErrorLogs().then(result => {
this.errors = result.data
})
}
},
created() {
this.load()
}
};
</script>
It works as it should, but the output for the stack trace takes up way too much space in the table column.
Ideally it should only show
org.springframework.web.method.annotation.MethodArgumentTypeMismatchException
and then if the user wants more detail they can click on the stack trace and get the full version in a pop up or something.
I am guessing the easiest solution would be to filter the stack trace, so that it does not show any text beyong the : sign.
But how would I implement this in the setup that I currently have?
I am guessing in computed properties I need add a method to the stackTrace field.
So:
{
key: 'stackTrace',
label: this.$t('errorLogs.stackTrace'),
sortable: true
function: this.filteredStackTrace()
},
And then create a new method.
filteredStackTrace(){
this.errors.stackTrace.filter(some filter...)
}
Maybe something like following snippet:
const app = Vue.createApp({
data() {
return {
st: `Exception in thread "main" java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)`,
expanded: false
};
},
computed: {
firstLine() {
return this.st.split('\n')[0]
},
allLines() {
return this.st.split('\n').filter((item, idx) => idx !== 0).toString()
}
},
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
{{ firstLine }}
<button #click="expanded = !expanded">all</button>
<div v-if="expanded">{{ allLines }}</div>
</div>

Trying to use Vue js plug-ins without the use of NPM or webpack

The problem
At this moment I am following the jqwidgets guidelines from the link displayed below to build a dropdownbox. The only problem with their setup is that they make use of the IMPORT functionality which I can not make use of due to restrictions from my techlead.
My question
Is there a way to make the plug-in work within my html file and without the IMPORT functionality through for example a CDN?
Maybe an even more important quest, is it possible to make use of Vue JS and it's plugins without the use of webpack and NPM?
Jqwidgets Vue
https://www.jqwidgets.com/vue-components-documentation/documentation/jqxdropdownlist/vue-dropdownlist-getting-started.htm?search=dropdown
What I have tried
About the CDN, I have tried to implement this part without much success, below is my current code:
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/vue-select#latest/dist/vue-select.css">
<style src="https://jqwidgets.com/public/jqwidgets/styles/jqx.base.css"></style>
<script src="https://unpkg.com/vue#latest"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jqwidgets-scripts#10.1.3/jqwidgets/jqx-all.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/http-vue-loader"></script>
</head>
<body>
<div id="app">
<jqx-DropDownList #select="onSelect($event)"
:width="200" :height="25"
:source="source" :selectedIndex="1">
</jqx-DropDownList>
</div>
<script type="text/javascript">
var filter = new Vue({
el: '#app',
components: {
'jqx-dropdownlist': httpVueLoader('https://cdn.jsdelivr.net/npm/jqwidgets-scripts#10.1.3/jqwidgets-vue/vue_jqxdropdownlist.vue')
},
data: function () {
return {
source: [
'Affogato',
'Americano',
'Bicerin',
'Breve',
'Café Bombón',
'Café au lait',
'Caffé Corretto',
'Café Crema',
'Caffé Latte',
'Caffé macchiato',
'Café mélange',
'Coffee milk',
'Cafe mocha',
'Cappuccino',
'Carajillo',
'Cortado',
'Cuban espresso',
'Espresso',
'Eiskaffee',
'The Flat White',
'Frappuccino',
'Galao',
'Greek frappé coffee',
'Iced Coffee',
'Indian filter coffee',
'Instant coffee',
'Irish coffee',
'Liqueur coffee'
]
}
},
beforeCreate: function () {
// Add here any data where you want to transform before components be rendered
},
methods: {
methods: {
onSelect: function () {
this.$refs.dropdownlist.close();
}
}
},
events: {
dataplotRollover: function (ev, props) {
chart.displayValue = props.displayValue
}
}
});
</script>
</body>
</html>
Download the package in a directory, e.g. assets or static, within your webroot and use the <script src="path_to that dir/js_file_you_need" /> to make it available to your page. Same for the CSS.

How to add title and script on vue template with nuxtjs

i want to add title, description and other html meta for SEO.
how i can do it in vue template?
for example i want to add the meta on my template.vue.
for some reason i have to add script too on that template.
my code is like this:
head: {
title: 'my title',
script: [
{ src: '/js/theme.js', defer: true }
]
},
code above is error.
if i use return like this:
head () {
return {
title: this.title,
meta: [
{ hid: 'description', name: 'description', content: 'My custom description' }
],
script: [
{ src: '/js/theme.js', defer: true }
]
}
}
meta will work, but the script will not showing.
like i say, i can't put the script on nuxt-config.js don't know why, but the page will error.
check this image hope it will help your problem

How to add external JS scripts to VueJS Components?

I've to use two external scripts for the payment gateways.
Right now both are put in the index.html file.
However, I don't want to load these files at the beginning itself.
The payment gateway is needed only in when user open a specific component (using router-view).
Is there anyway to achieve this?
Thanks.
A simple and effective way to solve this, it's by adding your external script into the vue mounted() of your component. I will illustrate you with the Google Recaptcha script:
<template>
.... your HTML
</template>
<script>
export default {
data: () => ({
......data of your component
}),
mounted() {
let recaptchaScript = document.createElement('script')
recaptchaScript.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
document.head.appendChild(recaptchaScript)
},
methods: {
......methods of your component
}
}
</script>
Source: https://medium.com/#lassiuosukainen/how-to-include-a-script-tag-on-a-vue-component-fe10940af9e8
I have downloaded some HTML template that comes with custom js files and jquery. I had to attach those js to my app. and continue with Vue.
Found this plugin, it's a clean way to add external scripts both via CDN and from static files
https://www.npmjs.com/package/vue-plugin-load-script
// local files
// you have to put your scripts into the public folder.
// that way webpack simply copy these files as it is.
Vue.loadScript("/js/jquery-2.2.4.min.js")
// cdn
Vue.loadScript("https://maps.googleapis.com/maps/api/js")
using webpack and vue loader you can do something like this
it waits for the external script to load before creating the component, so globar vars etc are available in the component
components: {
 SomeComponent: () => {
  return new Promise((resolve, reject) => {
  let script = document.createElement('script')
  script.onload = () => {
  resolve(import(someComponent))
  }
  script.async = true
  script.src = 'https://maps.googleapis.com/maps/api/js?key=APIKEY&libraries=places'
  document.head.appendChild(script)
  })
}
},
UPDATE: This no longer works in Vue 3. You will receive this error:
VueCompilerError: Tags with side effect ( and ) are ignored in client component templates.
If you are trying to embed external js scripts to the vue.js component template, follow below:
I wanted to add a external JavaScript embed code to my component like this:
<template>
<div>
This is my component
<script src="https://badge.dimensions.ai/badge.js"></script>
</div>
<template>
And Vue showed me this error:
Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as , as they will not be parsed.
The way I solved it was by adding type="application/javascript" (See this question to learn more about MIME type for js):
<script type="application/javascript" defer src="..."></script>
You may notice the defer attribute. If you want to learn more watch this video by Kyle
This can be simply done like this.
created() {
var scripts = [
"https://cloudfront.net/js/jquery-3.4.1.min.js",
"js/local.js"
];
scripts.forEach(script => {
let tag = document.createElement("script");
tag.setAttribute("src", script);
document.head.appendChild(tag);
});
}
You can use the vue-head package to add scripts, and other tags to the head of your vue component.
Its as simple as:
var myComponent = Vue.extend({
data: function () {
return {
...
}
},
head: {
title: {
inner: 'It will be a pleasure'
},
// Meta tags
meta: [
{ name: 'application-name', content: 'Name of my application' },
{ name: 'description', content: 'A description of the page', id: 'desc' }, // id to replace intead of create element
// ...
// Twitter
{ name: 'twitter:title', content: 'Content Title' },
// with shorthand
{ n: 'twitter:description', c: 'Content description less than 200 characters'},
// ...
// Google+ / Schema.org
{ itemprop: 'name', content: 'Content Title' },
{ itemprop: 'description', content: 'Content Title' },
// ...
// Facebook / Open Graph
{ property: 'fb:app_id', content: '123456789' },
{ property: 'og:title', content: 'Content Title' },
// with shorthand
{ p: 'og:image', c: 'https://example.com/image.jpg' },
// ...
],
// link tags
link: [
{ rel: 'canonical', href: 'http://example.com/#!/contact/', id: 'canonical' },
{ rel: 'author', href: 'author', undo: false }, // undo property - not to remove the element
{ rel: 'icon', href: require('./path/to/icon-16.png'), sizes: '16x16', type: 'image/png' },
// with shorthand
{ r: 'icon', h: 'path/to/icon-32.png', sz: '32x32', t: 'image/png' },
// ...
],
script: [
{ type: 'text/javascript', src: 'cdn/to/script.js', async: true, body: true}, // Insert in body
// with shorthand
{ t: 'application/ld+json', i: '{ "#context": "http://schema.org" }' },
// ...
],
style: [
{ type: 'text/css', inner: 'body { background-color: #000; color: #fff}', undo: false },
// ...
]
}
})
Check out this link for more examples.
With Vue 3, I use mejiamanuel57 answer with an additional check to ensure the script tag hasn't been loaded already.
mounted() {
const scripts = [
"js/script1.js",
"js/script2.js"
];
scripts.forEach(script => {
let tag = document.head.querySelector(`[src="${ script }"`);
if (!tag) {
tag = document.createElement("script");
tag.setAttribute("src", script);
tag.setAttribute("type", 'text/javascript');
document.head.appendChild(tag);
}
});
// ...
You can load the script you need with a promise based solution:
export default {
data () {
return { is_script_loading: false }
},
created () {
// If another component is already loading the script
this.$root.$on('loading_script', e => { this.is_script_loading = true })
},
methods: {
load_script () {
let self = this
return new Promise((resolve, reject) => {
// if script is already loading via another component
if ( self.is_script_loading ){
// Resolve when the other component has loaded the script
this.$root.$on('script_loaded', resolve)
return
}
let script = document.createElement('script')
script.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
script.async = true
this.$root.$emit('loading_script')
script.onload = () => {
/* emit to global event bus to inform other components
* we are already loading the script */
this.$root.$emit('script_loaded')
resolve()
}
document.head.appendChild(script)
})
},
async use_script () {
try {
await this.load_script()
// .. do what you want after script has loaded
} catch (err) { console.log(err) }
}
}
}
Please note that this.$root is a little hacky and you should use a vuex or eventHub solution for the global events instead.
You would make the above into a component and use it wherever needed, it will only load the script when used.
NOTE: This is a Vue 2.x based solution. Vue 3 has stopped supporting $on.
Are you using one of the Webpack starter templates for vue (https://github.com/vuejs-templates/webpack)? It already comes set up with vue-loader (https://github.com/vuejs/vue-loader). If you're not using a starter template, you have to set up webpack and vue-loader.
You can then import your scripts to the relevant (single file) components. Before that, you have toexport from your scripts what you want to import to your components.
ES6 import:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
- http://exploringjs.com/es6/ch_modules.html
~Edit~
You can import from these wrappers:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-paypal-checkout
The top answer of create tag in mounted is good, but it has some problems: If you change your link multiple times, it will repeat create tag over and over.
So I created a script to resolve this, and you can delete the tag if you want.
It's very simple, but can save your time to create it by yourself.
// PROJECT/src/assets/external.js
function head_script(src) {
if(document.querySelector("script[src='" + src + "']")){ return; }
let script = document.createElement('script');
script.setAttribute('src', src);
script.setAttribute('type', 'text/javascript');
document.head.appendChild(script)
}
function body_script(src) {
if(document.querySelector("script[src='" + src + "']")){ return; }
let script = document.createElement('script');
script.setAttribute('src', src);
script.setAttribute('type', 'text/javascript');
document.body.appendChild(script)
}
function del_script(src) {
let el = document.querySelector("script[src='" + src + "']");
if(el){ el.remove(); }
}
function head_link(href) {
if(document.querySelector("link[href='" + href + "']")){ return; }
let link = document.createElement('link');
link.setAttribute('href', href);
link.setAttribute('rel', "stylesheet");
link.setAttribute('type', "text/css");
document.head.appendChild(link)
}
function body_link(href) {
if(document.querySelector("link[href='" + href + "']")){ return; }
let link = document.createElement('link');
link.setAttribute('href', href);
link.setAttribute('rel', "stylesheet");
link.setAttribute('type', "text/css");
document.body.appendChild(link)
}
function del_link(href) {
let el = document.querySelector("link[href='" + href + "']");
if(el){ el.remove(); }
}
export {
head_script,
body_script,
del_script,
head_link,
body_link,
del_link,
}
And you can use it like this:
// PROJECT/src/views/xxxxxxxxx.vue
......
<script>
import * as external from '#/assets/external.js'
export default {
name: "xxxxxxxxx",
mounted(){
external.head_script('/assets/script1.js');
external.body_script('/assets/script2.js');
external.head_link('/assets/style1.css');
external.body_link('/assets/style2.css');
},
destroyed(){
external.del_script('/assets/script1.js');
external.del_script('/assets/script2.js');
external.del_link('/assets/style1.css');
external.del_link('/assets/style2.css');
},
}
</script>
......
Simplest solution is to add the script in the index.html file of your vue-project
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>vue-webpack</title>
</head>
<body>
<div id="app"></div>
<!-- start Mixpanel --><script type="text/javascript">(function(c,a){if(!a.__SV){var b=window;try{var d,m,j,k=b.location,f=k.hash;d=function(a,b){return(m=a.match(RegExp(b+"=([^&]*)")))?m[1]:null};f&&d(f,"state")&&(j=JSON.parse(decodeURIComponent(d(f,"state"))),"mpeditor"===j.action&&(b.sessionStorage.setItem("_mpcehash",f),history.replaceState(j.desiredHash||"",c.title,k.pathname+k.search)))}catch(n){}var l,h;window.mixpanel=a;a._i=[];a.init=function(b,d,g){function c(b,i){var a=i.split(".");2==a.length&&(b=b[a[0]],i=a[1]);b[i]=function(){b.push([i].concat(Array.prototype.slice.call(arguments,
0)))}}var e=a;"undefined"!==typeof g?e=a[g]=[]:g="mixpanel";e.people=e.people||[];e.toString=function(b){var a="mixpanel";"mixpanel"!==g&&(a+="."+g);b||(a+=" (stub)");return a};e.people.toString=function(){return e.toString(1)+".people (stub)"};l="disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split(" ");
for(h=0;h<l.length;h++)c(e,l[h]);var f="set set_once union unset remove delete".split(" ");e.get_group=function(){function a(c){b[c]=function(){call2_args=arguments;call2=[c].concat(Array.prototype.slice.call(call2_args,0));e.push([d,call2])}}for(var b={},d=["get_group"].concat(Array.prototype.slice.call(arguments,0)),c=0;c<f.length;c++)a(f[c]);return b};a._i.push([b,d,g])};a.__SV=1.2;b=c.createElement("script");b.type="text/javascript";b.async=!0;b.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?
MIXPANEL_CUSTOM_LIB_URL:"file:"===c.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";d=c.getElementsByTagName("script")[0];d.parentNode.insertBefore(b,d)}})(document,window.mixpanel||[]);
mixpanel.init("xyz");
</script><!-- end Mixpanel -->
<script src="/dist/build.js"></script>
</body>
</html>
The answer from mejiamanuel57 is great, but I want to add a couple of tips that work in my case (I spent some hours on them). First, I needed to use the "window" scope. Also, if you need to access any Vue element inside the "onload" function, you need a new variable for the "this" instance.
<script>
import { mapActions } from "vuex";
export default {
name: "Payment",
methods: {
...mapActions(["aVueAction"])
},
created() {
let paywayScript = document.createElement("script");
let self = this;
paywayScript.onload = () => {
// call to Vuex action.
self.aVueAction();
// call to script function
window.payway.aScriptFunction();
};
// paywayScript.async = true;
paywayScript.setAttribute(
"src",
"https://api.payway.com.au/rest/v1/payway.js"
);
document.body.appendChild(paywayScript);
}
};
</script>
I worked with this on Vue 2.6. Here there is an explanation about how the trick "let self = this;" works in Javascript:
What does 'var that = this;' mean in JavaScript?
A fast and easy way that i found to do it is like this:
<template>
<div>Some HTML</div>
<component
src="https://unpkg.com/flowbite#1.5.3/dist/flowbite.js"
:is="'script'"
></component>
</template>
mounted() {
if (document.getElementById('myScript')) { return }
let src = 'your script source'
let script = document.createElement('script')
script.setAttribute('src', src)
script.setAttribute('type', 'text/javascript')
script.setAttribute('id', 'myScript')
document.head.appendChild(script)
}
beforeDestroy() {
let el = document.getElementById('myScript')
if (el) { el.remove() }
}
To keep clean components you can use mixins.
On your component import external mixin file.
Profile.vue
import externalJs from '#client/mixins/externalJs';
export default{
mounted(){
this.externalJsFiles();
}
}
externalJs.js
import('#JSassets/js/file-upload.js').then(mod => {
// your JS elements
})
babelrc (I include this, if any get stuck on import)
{
"presets":["#babel/preset-env"],
"plugins":[
[
"module-resolver", {
"root": ["./"],
alias : {
"#client": "./client",
"#JSassets": "./server/public",
}
}
]
}
If you're using Vue 3 and the Composition API (I highly recommend), and you're using <script> tags a lot, you can write a "composable" function for this:
import { onMounted } from "vue";
export const useScript = (src, async = false, defer = false) => {
onMounted(() => {
// check if script already exists
if (document.querySelector(`head script[src="${src}"`)) return;
// add tag to head
const tag = document.createElement("script");
tag.setAttribute("src", src);
if (async) tag.setAttribute("async", "");
if (defer) tag.setAttribute("defer", "");
tag.setAttribute("type", "text/javascript");
document.head.append(tag);
});
};
OR, if you are using VueUse (I also highly recommend), you can use their existing useScriptTag function.
You can use vue-loader and code your components in their own files (Single file components). This will allow you to include scripts and css on a component basis.
well, this is my practice in qiokian (a live2d anime figure vuejs component):
(below is from the file src/qiokian.vue)
<script>
export default {
data() {
return {
live2d_path:
'https://cdn.jsdelivr.net/gh/knowscount/live2d-widget#latest/',
cdnPath: 'https://cdn.jsdelivr.net/gh/fghrsh/live2d_api/',
}
},
<!-- ... -->
loadAssets() {
// load waifu.css live2d.min.js waifu-tips.js
if (screen.width >= 768) {
Promise.all([
this.loadExternalResource(
this.live2d_path + 'waifu.css',
'css'
),
<!-- ... -->
loadExternalResource(url, type) {
// note: live2d_path parameter should be an absolute path
// const live2d_path =
// "https://cdn.jsdelivr.net/gh/knowscount/live2d-widget#latest/";
//const live2d_path = "/live2d-widget/";
return new Promise((resolve, reject) => {
let tag
if (type === 'css') {
tag = document.createElement('link')
tag.rel = 'stylesheet'
tag.href = url
} else if (type === 'js') {
tag = document.createElement('script')
tag.src = url
}
if (tag) {
tag.onload = () => resolve(url)
tag.onerror = () => reject(url)
document.head.appendChild(tag)
}
})
},
},
}
There is a vue component for this usecase
https://github.com/TheDynomike/vue-script-component#usage
<template>
<div>
<VueScriptComponent script='<script type="text/javascript"> alert("Peekaboo!"); </script>'/>
<div>
</template>
<script>
import VueScriptComponent from 'vue-script-component'
export default {
...
components: {
...
VueScriptComponent
}
...
}
</script>
If you are attempting to utilize a variable that is defined within a JavaScript file that is being loaded asynchronously and you receive an 'undefined' error, it is likely because the script has not yet finished loading. To resolve this issue, you can utilize the onload function to ensure that the script has completed loading before attempting to access the variable. As an example:
const script = document.createElement(...) // set attribute and so on...
script.onload = () => {
// do something with some variables/functions/logic from the loaded script
}
You can use the head property in vue to return a custom script
export default {
head: {
script: [{
src: 'https://cdn.polygraph.net/pg.js',
type: 'text/javascript'
}]
}
}

How to Troubleshooting Binding

I found a cool project (RoboJS), and I forked it: Forked Repo. My plan was to try to add a nice front end with Polymer 1.0 and learn a little in the process.
What I am having trouble with is getting the binding to show in my component. I've built a really simple "robot" component to show the status of the robot during the game.
To start, all I want to do is to show the name in the title, but it comes out blank. Here's the component:
<dom-module id="robojs-robot-status">
<template>
<div>Robot Name <span>[[robot]]</span><span>{{test}}</span></div>
</template>
</dom-module>
<script>
Polymer({
is: "robojs-robot-status",
properties: {
robot: {
type: String,
value: "testing"
},
test: {
type: String,
value: "testing2"
}
},
ready: function() {
},
init: function() {
console.log(this.robot);
console.log(this.test);
}
});
</script>
On the parent component, I set the robot attribute:
Here's the attribute:
<link rel="import" href="robojs-robot-status.html">
<robojs-robot-status robot="{{robot}}"></robojs-robot-status>
And, I have a script that, for now, sets the value on the ready event:
Polymer({
is: "robojs-arena",
properties: {
robot: {
type: String,
value: "hello"
}
},
ready: function() {
this.games = window.roboJS.games;
console.log(this.games);
//this.robot = {name: "hello"};
this.robot = "hello";
},
init: function() {
console.log("******* init *******");
console.log(this.robot);
document.querySelector("robojs-robot-status").init();
},
pause: function() {
window.roboJS.pause();
},
start: function() {
console.log(window.roboJS);
window.roboJS.resume();
}
});
[[robot]] is blank. {{test}} binds to "testing2".
Using {{robot}} or [[robot]] doesn't make a difference. So, that doesn't have an impact.
If I remove, the "robot" attribute in the parent component, the value works. It shows "testing". So, it is binding, but not with the actual value.
Beyond figuring out what I am doing wrong in this instance, is there a good way to troubleshoot? I am having similar issues in other places in the app.
If this were Angular + jQuery, I would do something like this:
$('robotjs-robot-status').scope().$eval("robot")
I could type that into the developer console in Chrome and see what it said and troubleshoot. I could also use the Batarang extension in Chrome.
With Polymer, I am not sure where to start. Any help/ideas?
If the parent snippet is posted here exactly as it appears in the code, then it's probably to blame. The
<link rel="import" href="robojs-robot-status.html">
should be outside , like
<dom-module id="robojs-robot">
<link rel="import" href="robojs-robot-status.html">
<template>
<robojs-robot-status robotname="{{robotname}}"></robojs-robot-status>
</template>
<script>
Polymer({
is: "robojs-robot",
ready: function() {
console.log('setting to Dilly');
this.robotname = "Dilly";
},
properties: {
robotname: {
type: String,
value: "hello"
}
},
});
</script>
</dom-module>
and then if status is
<dom-module id="robojs-robot-status">
<template>
<div>Robot Name <span>[[robotname]]</span></div>
</template>
<script>
Polymer({
is: "robojs-robot-status",
properties: {
robotname: {
type: String,
value: "testing",
observer: '_robotnameChanged'
}
},
_robotnameChanged: function(newValue, oldValue) {
console.log('_robotnameChanged: newValue='+newValue+' oldValue='+oldValue)
}
});
</script>
</dom-module>
everything works for me.
PS: properties seem to be not really needed here as binding is unidirectional.

Categories