I have a login component, and I'd like to make the login status available for other components in my application.
Can anyone provide working code or examples?
I need some sort of binding or eventing at least, so that when the login status changes, the UI of these other interested components can be updated accordingly.
Create a property that represents the status in your login component and set notify: true.
Use data-binding in your login component and any other components that use that status.
<login-component status="{{status}}"></login-component>
<other-component login="{{status}}"></other-component>
If you use your components outside of a Polymer template, make use of autobind by wrapping them in a <template is="dom-bind">.
<template is="dom-bind">
<login-component status="{{status}}"></login-component>
<other-component login="{{status}}"></other-component>
</template>
You can use <iron-localstorage> as described here.
<dom-module id="ls-sample">
<iron-localstorage name="my-app-storage"
value="{{cartoon}}"
on-iron-localstorage-load-empty="initializeDefaultCartoon"
></iron-localstorage>
</dom-module>
<script>
Polymer({
is: 'ls-sample',
properties: {
cartoon: {
type: Object
}
},
// initializes default if nothing has been stored
initializeDefaultCartoon: function() {
this.cartoon = {
name: "Mickey",
hasEars: true
}
},
// use path set api to propagate changes to localstorage
makeModifications: function() {
this.set('cartoon.name', "Minions");
this.set('cartoon.hasEars', false);
}
});
</script>
See this Plunker example (by #nazerke) demonstrating one component observing another's property.
http://plnkr.co/edit/p7R8BqJJfoYMVA3t3DbX?p=preview
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://www.polymer-project.org/1.0/samples/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="parent-element.html">
<link rel="import" href="first-child.html">
<link rel="import" href="second-child.html"> </head>
<body>
<parent-element></parent-element>
</body>
</html>
parent-element.html
<link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<dom-module id="parent-element">
<template>
<first-child prop={{value}}></first-child>
<second-child feat1={{prop}}></second-child> In parent-element
<h1>{{value}}</h1> </template>
<script>
Polymer({
is: "parent-element",
properties: {
value: {
type: String
}
},
valueChanged: function() {
console.log("value changed");
}
});
</script>
</dom-module>
first-child.html
<link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<dom-module id="first-child">
<template>
<p>first element.</p>
<h2>{{prop}}</h2> </template>
<script>
Polymer({
is: "first-child",
properties: {
prop: {
type: String,
notify: true
}
},
ready: function() {
this.prop = "property";
}
});
</script>
</dom-module>
second-child.html
<link rel="import" href="http://www.polymer-project.org/1.0/samples/components/polymer/polymer.html">
<dom-module id="second-child">
<template>
<p>Second element.</p>
<h2>{{feat1}}</h2> </template>
<script>
Polymer({
is: "second-child",
properties: {
feat1: {
type: String,
notify: true,
value: "initial value"
}
},
ready: function() {
this.addEventListener("feat1-changed", this.myAct);
},
myAct: function() {
console.log("feat1-changed ", this.feat1);
}
});
</script>
</dom-module>
You can use <iron-meta> as described here:
<iron-meta key="info" value="foo/bar"></iron-meta>
...
meta.byKey('info').getAttribute('value').
or
document.createElement('iron-meta').byKey('info').getAttribute('value');
or
<template>
...
<iron-meta id="meta"></iron-meta>
...
this.$.meta.byKey('info').getAttribute('value');
....
</template>
Related
I want Nuxtjs render Vue-Components dynamically. In Vuejs I get it working like that. But this does not work with nuxt, which I dont understand:
https://codesandbox.io/s/young-wood-lw0gl
<html>
<head>
<title>Vue Component Blog Post Example</title>
<script src="https://unpkg.com/vue"></script>
<link rel="stylesheet" type="text/css" href="/style.css" />
</head>
<body>
<div id="dynamic-component-demo">
<component v-bind:is="testcomp" class="tab"></component>
</div>
<script>
new Vue({
el: "#dynamic-component-demo",
data: {
text: "Text",
button: "<button>Save</button>",
currentTab: "Posts",
tabs: ["Posts", "Archive"]
},
computed: {
testcomp() {
Vue.component("testcomp", {
template: `<div>Archive components ${this.text}
${this.button}
</div>`
});
return "testcomp";
}
}
});
</script>
</body>
</html>
But in Nuxtjs, it doesnt show anything
<template>
<section>
test
<component v-bind:is="testcomp" class="tab"></component>
</section>
</template>
<script>
import Vue from 'vue'
export default {
data() {
return {
text: 'Test',
button: '<button>Save</button>'
}
},
computed: {
testcomp() {
Vue.component("testcomp", {
template: `<div>Archive components ${this.text}
${this.button}
</div>`
});
return "testcomp";
}
}
}
</script>
I guess I have to wrap it into Nuxt with vue.use() somewhere or so. But I am not sure exactly
I have a basic Example Component setup which is binded to a Vue Instance like so
<template>
<div class="container-fluid">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
{{ msg }}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data : function(){
return{
msg : "Hello"
}
},
mounted() {
console.log('Component mounted.')
}
}
</script>
And this is my app.js file
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('example-component', require('./components/ExampleComponent.vue'));
var firstComponent = new Vue({
el: '#app'
});
This is my HTML
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
</head>
<body>
<div id="app">
<example-component></example-component>
</div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
How can I now change the value of msg? I don't have any reference to that component anywhere? How can I do that?
Is this possible?
var ex = Vue.component('example-component', require('./components/ExampleComponent.vue'));
ex.data = "new Value";
add props property to your component and set inside it the msg property :
<script>
export default {
props:{
msg:{
type:String,
default:"Hello"
}
},
data : function(){
},
mounted() {
console.log('Component mounted.')
}
}
</script>
and
<example-component msg="new Hello"></example-component>
UPDATE
after understanding your use case i recommend to use child component ref
const ExampleComponent = Vue.component('example-component', {
template: `
<div>
<h2>Example component</h2>
<div>{{msg}}</div>
</div>
`,
data() {
return {
msg: "Hello"
}
}
});
window.root = new Vue({
el: '#app',
components: {
ExampleComponent
}
});
root.$refs.example.msg = "new hello"
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h2>Parent</h2>
<example-component ref="example"></example-component>
</div>
</body>
</html>
TL;DR Have a look at this example, it does what you want: https://codesandbox.io/s/88ojwpjq88
You need to distinguish between data (the components private data) and props (data passed to the child component). Read this section of the Vue.js guide: https://v2.vuejs.org/v2/guide/components.html
In your component, you'll need to declare the prop:
export default {
props : ['msg'],
mounted() {
console.log('Component mounted.')
}
}
Then you can bind a data to the child component like this:
<example-component :msg="myMessage"></example-component>, assuming the parent component has myMessage declared like this:
data : function(){
return {
myMessage : "Hello"
}
}
To change the value, you can bind it to some sort of input. Here's an example w/ a text field: <input v-model="myMessage">.
If you enter sth. into this field, you should see the bound value in your component update.
Do read the manual here: https://v2.vuejs.org/v2/guide/index.html. It's really good, your questions are covered entirely in there.
Add the property to your component, make it parent-to-child, that is, you will bind the property within the component, and you can pass data to that property.
Depending on the flow, you must identify how you will do this, whether it is from father to son or from child to father. To pass data to child, you pass through props, if you pass from child to parent, you will use $ emit.
https://v2.vuejs.org/v2/guide/components.html#Passing-Data-to-Child-Components-with-Props
If you use parent to child you will do it the following way.
Pai.vue
<template>
<div> {{msg}} </div>
</template>
<script>
export default {
props: {
msg: {
type: String,
default: 'Hello'
}
}
}
</script>
Ai Inside the child component you call the parameter
<template>
<div>
<parent :msg="valueMsg"/>
</div>
</template>
enter code here
son.vue
<script>
import pai from './pai'
export default {components: {parent},
data: () => ({
valueMsg = 'Hello Test'
})
}
https://jsfiddle.net/hamiltongabriel/3zr8jb7r/
I want to create basic sample of single file component in vue. I have configured webpack to compile my code and it works fine. Now i want to pass props to component and i get error that props is undefined.
index file
<head>
<meta charset="UTF-8">
<title>Vue Webpack Demo</title>
<script type="text/javascript" src="/dist/vue.js"></script>
</head>
<body>
<div id="mainContent">
<main-content post-title="hello!"></main-content>
</div>
</body>
<script src="/dist/index.js"></script>
index.js file
import Vue from 'vue';
import MainContent from './views/main-content';
let MainComponent = Vue.extend(MainContent);
new MainComponent().$mount("#mainContent");
main-content.vue
<template src="./main-content.html"></template>
<style scoped lang="scss" src="./main-content.scss"></style>
<script>
export default {
name: "main-content",
props: {
postTitle:{
type:String,
required:true
}
},
data: () => ({
webpack: 'Powered by webpack!?',
name:'name'
}),
}
</script>
The way you are setting up the application is awkward. There is no wrapper for the application. Following the following example to see how it can be orchestrated to finally have your component with the required prop
The index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>CodeSandbox Vue</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
The main.js where the vue application is created:
import Vue from "vue";
import App from "./App";
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
Now the App uses your component MainContent and passes the prop:
<template>
<MainContent post-title="Hello!"/>
</template>
<script>
import MainContent from "./views/MainContent";
export default {
name: "App",
components: {
MainContent
}
};
</script>
Finally the component reads the prop:
<template>
<div class="hello">
post-title: {{ postTitle }}
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
postTitle: {
type: String,
required: true
}
},
};
</script>
You can see this example working here
I'm trying to create a new element for Polymer 2.x in class syntax, but now I can't use the IronA11yKeysBehavior. What am I doing wrong here?
<link rel="import" href="https://raw-dot-custom-elements.appspot.com/PolymerElements/iron-a11y-keys-behavior/v2.0.0/polymer/polymer.html">
<link rel="import" href="https://raw-dot-custom-elements.appspot.com/PolymerElements/iron-a11y-keys-behavior/v2.0.0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="https://raw-dot-custom-elements.appspot.com/PolymerElements/paper-input/v2.0.0/paper-input/paper-input.html">
<dom-module id="my-control">
<template>
Template Content! Pressing enter should show an alert message. [[result]]
<paper-input label="Demo Template Input" value="{{result}}"></paper-input>
</template>
<script>
"use strict";
class MyControl extends Polymer.mixinBehaviors([
Polymer.IronA11yKeysBehavior
], Polymer.Element){
static get is(){return 'my-control'; }
static get keyBindings(){
return {
'enter': '_updatePressed'
};
}
static get instanceKeyBindings(){
return {
'enter': '_updatePressed'
};
}
_updatePressed(event){
console.log(event.detail);
this.result = "Enter pressed";
alert("Enter pressed");
}
}
customElements.define(MyControl.is, MyControl);
</script>
</dom-module>
<my-control></my-control>
When I use the old syntax, everything works fine.
<link rel="import" href="https://raw-dot-custom-elements.appspot.com/PolymerElements/iron-a11y-keys-behavior/v2.0.0/polymer/polymer.html">
<link rel="import" href="https://raw-dot-custom-elements.appspot.com/PolymerElements/iron-a11y-keys-behavior/v2.0.0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="https://raw-dot-custom-elements.appspot.com/PolymerElements/paper-input/v2.0.0/paper-input/paper-input.html">
<dom-module id="my-control">
<template>
Template Content! [[result]]
<paper-input label="Demo Template Input" value="{{result}}"></paper-input>
</template>
<script>
"use strict";
Polymer({
is: 'my-control',
behaviors: [
Polymer.IronA11yKeysBehavior
],
keyBindings: { 'enter': '_updatePressed' },
_updatePressed: function(event){
console.log(event.detail);
this.result = "Enter pressed";
alert("Enter pressed");
}
});
</script>
</dom-module>
<my-control></my-control>
How do I use the behavior with the new class syntax?
keyBindings should be an instance getter instead of a static one. Otherwise, it looks like your code is correct.
class MyControl extends Polymer.mixinBehaviors([Polymer. IronA11yKeysBehavior], Polymer.Element) {
// static get keyBindings() { ... } // DON'T DO THIS
get keyBindings() { ... } // DO THIS
}
Here's your code snippet corrected:
<base href="https://cdn.rawgit.com/download/polymer-cdn/2.6.0.2/lib/">
<script src="webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="paper-input/paper-input.html">
<dom-module id="my-control">
<template>
Template Content! Pressing enter should show an alert message. [[result]]
<paper-input label="Demo Template Input" value="{{result}}"></paper-input>
</template>
<script>
"use strict";
class MyControl extends Polymer.mixinBehaviors([
Polymer.IronA11yKeysBehavior
], Polymer.Element){
static get is(){return 'my-control'; }
get keyBindings(){
return {
'enter': '_updatePressed'
};
}
static get instanceKeyBindings(){
return {
'enter': '_updatePressed'
};
}
_updatePressed(event){
console.log(event.detail);
this.result = "Enter pressed";
alert("Enter pressed");
}
}
customElements.define(MyControl.is, MyControl);
</script>
</dom-module>
<my-control></my-control>
It looks like the IronA11yKeysBehavior repo currently only has a legacy demo, but I've translated it to Polymer 2's class based syntax in this Codepen.
I am trying to get a basic dom-repeat working with Polymer 2.0
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<dom-module id="dom-repeat-test">
<template>
<style>
:host {
display: block;
}
</style>
<h2>[[title]]!</h2>
<template is="dom-repeat" items="{{employees}}">
<div>First name: <span>{{item.first}}</span></div>
<div>Last name: <span>{{item.last}}</span></div>
</template>
</template>
<script>
/**
* #customElement
* #polymer
*/
class DomRepeatTest extends Polymer.Element {
static get is() { return 'dom-repeat-test'; }
static get properties() {
return {
title: {
type: String,
value: 'dom-repeat-test'
},
employees: {
type: Array,
value: [
{first: 'Bob', last: 'Smith'},
{first: 'Sally', last: 'Johnson'}
]
}
};
}
}
window.customElements.define(DomRepeatTest.is, DomRepeatTest);
</script>
</dom-module>
I am getting an empty dom-repeat element in the output in the inspector but no elements in it and also no errors in the console.
Heres the code :-
https://github.com/AaronNGray/polymer-dom-repeat-test
If you're not importing polymer.html, import dom-repeat.html.
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">
See https://www.polymer-project.org/2.0/docs/devguide/templates#dom-repeat