I'm following the codelab for Polymerfire and first bit of tinkering, wanted to change the login element from using google sign in to use email / password.
The element works but I've been having trouble trying to access the values of the email / password field outside of the element itself.
I would've thought that I could access the value of the email textfield by referencing this.$.login.email.value but that doesn't work.
Here's my code
The login element
<dom-module id="as-login">
<template>
<!-- Here we stick in our login fields -->
<paper-input id="email" label="Email"></paper-input>
<paper-input id="password" label="Password" type="password"></paper-input>
<paper-button id="login" on-tap="signIn" disabled="[[disabled]]">
<iron-icon icon="account-circle"></iron-icon>
<span>Sign in</span>
</paper-button>
</template>
<script>
Polymer({
is: 'as-login',
properties: {
disabled: {
type: Boolean,
reflectToAttribute: true,
value: false
},
signedIn: {
type: Boolean,
reflectToAttribute: true,
value: false
}
},
signIn: function() {
this.fire('sign-in', null, { bubbles: false });
},
clearEmail: function() {
this.$.email.value = "";
},
clearPassword: function() {
this.$.password.value = "";
},
getEmail: function() {
return(this.$.email.value);
},
getPassword: function() {
return(this.$.password.value);
},
});
</script>
</dom-module>
And here is the app element
<as-login
id="login"
on-sign-in="signIn"
signed-in="[[signedIn]]"
disabled="[[!online]]">
</as-login>
<script>
Polymer({
is: 'as-app',
behaviors: [Polymer.AsAppBehaviour],
signIn: function() {
console.log("Let one sign in");
// Process sign in promise
this.$.auth.signInWithEmailAndPassword(this.$.login.getEmail(), this.$.login.getPassword())
.then(function(res) {
console.log("We signed in");
})
.catch(function(err) {
console.log("We got an error");
});
},
signOut: function() {
console.log("Let one sign out");
this.$.auth.signOut();
}
});
</script>
Data binding is recommended - see the attributes, value
<paper-input id="email" label="Email" value="{{email}}"></paper-input>
<paper-input id="password" label="Password" type="password" value="{{password}}"></paper-input>
The values can be accessed in your JS like this (instead of accessing the value through dom, this.$.login.email.value)
getEmail: function() {
return this.email;
},
getPassword: function() {
return this.password;
},
Related
In my vue.js application, I am trying to render the html content dynamically in child component's slot. If I enter the text only then there is no issue, it works with fine.
Here is my code:
ChildComponent.vue
<template>
<div :class="type" class="message" v-if="type">
<slot />
</div>
</template>
<script>
export default {
...
props: ['type'],
...
}
</script>
ParentComponent.vue
<script>
import Alert from '#/Alert';
export default {
components: {
Alert,
},
data() {
return {
...
alert: {
error: '',
message: '',
}
};
},
created () {
this._onLoad()
},
methods: {
_onLoad() {
axios.get(`api.call.here`).then((res) => {
...
}).catch(error => {
this.alert.error = error.type;
this.alert.message = `<p>message here</p>`; // from response
});
},
}
}
</script>
Here is the screenshot of the issue:
What you trying to do can be achieved with v-html. You can use it while calling your ChildComponent.vue. This is a small example for your case:
<Alert>
<span v-html="alert.message"></span>
</Alert>
I created this <input> Vue component that handles a v-model property.
Adding the two-way data binding wasn't a problem, but I now want to add the current input value to the "state" so that I can clear it by just modifying a ref.
clearValue is called as expected but updating inputValue doesn't update the UI. What should I be doing differently ?
<template>
<div>
<input
:id="id"
type="text"
:value="inputValue"
#input="updateValue"
/>
<UiIcon
type="x"
#click.native="clearValue"
/>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from '#nuxtjs/composition-api';
import UiIcon from '~/components/ui/UiIcon.vue';
export default defineComponent({
name: 'UiInput',
components: { UiIcon },
props: {
id: {
type: String,
required: true,
},
value: {
type: String,
default: undefined,
},
},
setup(props, { emit }) {
const inputValue = ref(props.value);
const clearValue = () => {
inputValue.value = '';
};
const updateValue = (event: Event) => {
emit('input', (event.target as HTMLInputElement).value);
};
return {
updateValue,
clearValue,
inputValue,
};
},
});
Usage example
data() {
return { text: '' };
},
template: `
<div>
<UiInput :id="id" v-model="text" />
</div>
`,
I think you just need to emit 'input' event with empty value inside clearValue function
emit('input', '');
I need to clean up the google autocomplete input after select a location. I assigned a data value to the value prop of the component but seems like it doesn't change. Even using a watch, seem's like nothing happens.
This is my InputPlace component:
<template>
<label class="form-label-place" for="city">
<input class="form-control pr-5" :value="value" type="text" id="inputPlace" name="city" placeholder="Ingresa tu ciudad">
</label>
</template>
<script>
export default {
name: 'input-place',
props: {
value: ''
},
mounted() {
// Google autocomplete
const options = {
types: ['(cities)'],
componentRestrictions: {country: "PE"}
};
const places = new google.maps.places.Autocomplete(document.getElementById('inputPlace'), options);
google.maps.event.addListener(places, 'place_changed', () => {
this.$parent.placeChanged(places)
});
}
}
</script>
And this is how i'm using it into the view:
<template>
...
<input-place :value="InputPlaceValue"></input-place>
</template>
<script>
...
data() {
return {
activePlaces: [],
InputPlaceValue: ''
}
},
methods: {
placeChanged(places) {
let placeName = places.getPlace().name;
if(!this.activePlaces.includes(placeName)) this.activePlaces.push(placeName)
this.InputPlaceValue = ''
}
}
</script>
Hope you can help me, Thank you.
One option to clear autocomplete text field would be to:
a) use v-model directive
<input v-model="selectedAddress" class="form-control pr-5" type="text" id="inputPlace" name="city" placeholder="Ingresa tu ciudad">
b) and clear input value once place_changed event is triggered like this:
google.maps.event.addListener(places, "place_changed", () => {
this.selectedAddress = "";
});
InputPlace.vue example
<template>
<label class="form-label-place" for="city">
<input class="form-control" type="text" id="inputPlace" v-model="selectedAddress" name="city" placeholder="Search..">
</label>
</template>
<script>
export default {
/* global google */
name: "input-place",
data () {
return {
selectedAddress: ''
}
},
mounted() {
const options = {
types: ["(cities)"]
};
const places = new google.maps.places.Autocomplete(
document.getElementById("inputPlace"),
options
);
google.maps.event.addListener(places, "place_changed", () => {
this.selectedAddress = "";
this.$parent.placeChanged(places)
});
}
};
</script>
I have a vue app and a component. The app simply takes input and changes a name displayed below, and when someone changes the name, the previous name is saved in an array. I have a custom component to display the different list items. However, the component list items do not render immediately. Instead, the component otems render as soon as I type a letter into the input. What gives? Why would this not render the list items immediately?
(function(){
var app = new Vue({
el: '#app',
components: ['name-list-item'],
data: {
input: '',
person: undefined,
previousNames: ['Ian Smith', 'Adam Smith', 'Felicia Jones']
},
computed: {
politePerson: function(){
if(!this.person) {
return 'Input name here';
}
return "Hello! To The Venerable " + this.person +", Esq."
}
},
methods: {
saveInput: function(event){
event.preventDefault();
if(this.person && this.previousNames.indexOf(this.person) === -1) {
this.previousNames.push(this.person);
}
this.setPerson(this.input);
this.clearInput();
},
returnKey: function(key) {
return (key + 1) + ". ";
},
clearInput: function() {
this.input = '';
},
setPerson: function(person) {
this.person = person;
}
}
});
Vue.component('name-list-item', {
props: ['theKey', 'theValue'],
template: '<span>{{theKey}} {{theValue}}</span>'
});
})()
And here is my HTML.
<div id="app">
<div class="panel-one">
<span>Enter your name:</span>
<form v-on:submit="saveInput">
<input v-model="input"/>
<button #click="saveInput">Save</button>
</form>
<h1>{{politePerson}}</h1>
</div>
<div class="panel-two">
<h3>Previous Names</h3>
<div>
<div v-for="person, key in previousNames" #click='setPerson(person)'><name-list-item v-bind:the-key="key" v-bind:the-value="person" /></div>
</div>
</div>
</div>
You are not defining your component until after you have instantiated your Vue, so it doesn't apply the component until the first update.
I am trying to integrate dropzone.js and cloudinary into Polymer 1.0. It does work, but I am hitting a stumbling block on how to send the dynamic URL generated by Cloudinary back to Polymer so I can write that URL into Firebase. I am inside a function listening to dropzone events with the intention of using iron-signals to signal a different web component. "this" is now scoped to dropzone.js and not Polymer.
..resulting in "Uncaught TypeError: this.fire is not a function".
The code is below, I am trying to start the iron-signal based on listening the dropzone.js "success" event which provides access to the new image URL.
<link rel="stylesheet" href="../../../bower_components/dropzone/dist/min/dropzone.min.css">
<dom-module id="my-dropzone">
<style>
:host {
display: block;
}
div#my-dropzone-area {
max-width=300px;
height=300px;
border: 4px dashed blue;
}
</style>
<template>
<paper-button on-tap="startTheMessage">Test Fire!</paper-button>
<iron-signals on-iron-signal-hello="passTheMessage">
<div class="dropzone" id="my-dropzone-area">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</div>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'my-dropzone',
ready: function() {
// access a local DOM element by ID using this.$
Dropzone.options.myDropzoneArea = {
paramName: 'file', // The name that will be used to transfer the file
maxFilesize: 10, // MB
uploadMultiple: false,
acceptedFiles: '.jpg,.png,.jpeg,.gif',
parallelUploads: 6,
addRemoveLinks: true,
url: 'https://api.cloudinary.com/v1_1/remarkable-ky/image/upload',
init: function() {
this.on('addedfile', function(file) {
console.log('Added file.');
console.log(file);
});
this.on('sending', function(file, xhr, formData) {
console.log('Sending file.');
formData.append('api_key', 0000000000000);
formData.append('timestamp', Date.now() / 1000);
formData.append('upload_preset', 'where-ky');
});
this.on('success', function(file, response) {
var baseURL = 'http://res.cloudinary.com/remarkable-ky/image/upload/';
var url = baseURL.concat(response.public_id);
console.log('Cloudinary URL: ', url);
this.fire('iron-signal', {
name: 'hello',
data: null
});
});
}
};
},
startTheMessage: function() {
this.fire('iron-signal', {
name: 'hello',
data: null
});
},
passTheMessage: function() {
alert("got it");
},
properties: {},
});
})();
</script>
<script src="../../../bower_components/dropzone/dist/min/dropzone.min.js"></script>
you can pass this into the function with the .bind() function.
this.on('success', function(file, response) {
var baseURL = 'http://res.cloudinary.com/remarkable-ky/image/upload/';
var url = baseURL.concat(response.public_id);
console.log('Cloudinary URL: ', url);
this.fire('iron-signal', {
name: 'hello',
data: null
});
}.bind(this));