Attribute bind-value is not set in iron-input when initiated - data-binding

Here's a pattern I try to do with Polymer:
<link rel="import" href="/bower_components/polymer/polymer.html" />
<link rel="import" href="/bower_components/iron-ajax/iron-ajax.html" />
<link rel="import" href="/bower_components/iron-input/iron-input.html" />
<dom-module id="my-entity">
<template>
<iron-ajax auto url="{{urlGet}}" handle-as="json" last-response="{{entity}}"></iron-ajax>
<iron-ajax id="updateEntityCall" url="{{urlUpdate}}" handle-as="json" on-response="handleUpdateResponse"></iron-ajax>
<div>
<div class="input-wrapper">
<label>Name : </label>
<input is="iron-input" bind-value="{{entityName}}" value="{{entity.name}}" />
</div>
<div>
<button on-click="saveEntity">Save</button>
</div>
</div>
</template>
<script>
Polymer(
{
is: "my-entity",
properties: {
entityid: {
notify: true
},
entityName: {
notify: true
}
urlGet: {
computed: 'getUrlGet(entityid)'
},
urlTemplate: {
computed: 'getUrlUpdate(entityid, entityName)'
},
},
getUrlGet: function (entityId) {
return ['/path/to/get', entityId].join('/');
},
getUrlUpdate: function (entityId, entityName) {
return ['/path/to/update', entityId, entityName].join('/');
},
saveEntity: function (e, detail, sender) {
this.$.updateEntityCall.generateRequest();
}
}
);
</script>
</dom-module>
I first create a iron-ajax that will get some data from an entity. This will be printed in a iron-input element so a person will be able to update this entity.
The iron-ajax is bound to a {{entity}} variable that is used by the value in the iron-input element (entity.name). I have created a property called entityName that will be bound at the bind-value attribute of this same iron-input.
Once someone has made the change, the goal is that he/she clicks on the button that calls the function saveEntity, that basically call the other iron-ajax element.
There is no problem with this code when someone actually change the value of the iron-input. The problem appear when the user don't change the value and click the button. It sends nothing, like if entityName is not set.
This is a simple example, in my use-case I have 3 fields and 2 of them can have "empty strings" as valid value.

Related

Data Binding between parent and child component in vue3 composition api

I have successfully bound data in a two way format in vue 3 like this :
<template>
<p for="">Year of Incorporation</p>
<input type="text" v-model="input" />
<div>
{{ input }}
</div>
</template>
<script>
export default {
setup() {
let input = ref("")
return {input};
},
};
</script>
What I want to do now is put the input inside a child component like this:
Parent Component:
<template>
<Child v-model="input" />
{{input}}
</template>
Child Component:
<template>
<input type="text" v-model="babyInput" />
</template>
<script>
export default {
setup() {
let babyInput = ref("")
return {babyInput};
},
};
</script>
The Vue.js documentation presents a nice way of handling v-model-directives with custom components:
Bind the value to the child component
Emit an event when the Child's input changes
You can see this example from the docs with the composition when you toggle the switch in the right-top corner (at https://vuejs.org/guide/components/events.html#usage-with-v-model).

Polymer 2.0 + firebase can't update properly

I've got a problem using Polymer 2.0 and Firebase.
I want to update data to Firebase with firebase-document but when I want to update only the title, it destroy all the previous data and save only the title.
Example of the strucute before update :
myapp:
categories:
1:
logoName: test.png
title: test
And after :
myapp:
categories:
1:
title: test bis
Do I have to give always the entire record and update only the field I want or can I only give the field I want to update to saveValue.
I try to only give the field but it doesn't seem to work
Here is a part of my code :
<dom-module id="categorie-form">
<template>
<firebase-document
id="document"
app-name="myapp"
data="{{categorieData}}">
</firebase-document>
<iron-form id="categorieIronForm">
<form id="categorieForm">
<label for="title">Nom de la catégorie</label>
<input type="text" name="title" id="title" value="[[name]]">
<paper-button id="validButton" on-click="_submitCategorie" raised>valider</paper-button>
</form>
</iron-form>
</template>
<script>
class CategorieForm extends Polymer.Element {
static get is () { return "categorie-form" }
static get properties () {
return {
categorieData: {
type: Object
}
}
}
_submitCategorie () {
this.categorieData = {
title: form.title.value
};
this.$.document.saveValue('/categories', key)
}
}
customElements.define(CategorieForm.is, CategorieForm);
</script>
</dom-module>
Thank you
try this :
this.$.document.saveValue('/categories/1/title', key)

polymerfire create uid path in firebase database for new loggedin user

I am new to polymer and firebase. I could not find good documentation on firebase-document element for polymer.
My question is when a new user is logged in, how can I create an object in firebase database with his uid?
Also, please point me to some good examples on how to save and query the data using polymerfire firebase elements.
To begin with, you'll need firebase-auth to make authentication magic happen. For example, if you want to do a Google login, you need:
Assign these properties to firebase-auth element
<firebase-auth
id="auth"
user="{{user}}"
provider="google"
signed-in="{{signedIn}}">
</firebase-auth>
Assign click/tap event listener to button
<button on-tap="signInWithGoogle">Sign In With Google</button>
Call OAuth authentication method on button click/tap
signInWithGoogle: function() {
this.$.auth.signInWithPopup();
}
Now, here's how you save user information to firebase database:
Assign these properties to firebase-document element (mind that path property is irrelevant at this point as it will be overridden with save() method)
<firebase-document
id="authDocument"
data="{{userData}}">
</firebase-document>
Extend signInWithGoogle() method
signInWithGoogle: function() {
// Chain then() method to the Promise
this.$.auth.signInWithPopup().then(function(response) {
// Update userData object with user information
// returned with signInWithPopup()
this.userData.displayName = response.user.displayName;
this.userData.email = response.user.email;
// Save userData object under /users/$uid. Note that at this
// point authDocument's path is now changed to /users/$uid
this.$.authDocument.save('/users', response.user.uid);
// And don't forget to bind this
}.bind(this));
}
Hope that helped. Here's a full implementation in single element. Mind that firebase-app element is in parent.
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/polymerfire/firebase-auth.html">
<link rel="import" href="../bower_components/polymerfire/firebase-document.html">
<dom-module id="my-account">
<template>
<style>
:host {
display: block;
}
</style>
<firebase-auth
id="auth"
user="{{user}}"
provider="google"
signed-in="{{signedIn}}">
</firebase-auth>
<firebase-document
id="authDocument"
data="{{userData}}">
</firebase-document>
<div hidden$="[[user]]">
<button on-tap="signInWithGoogle">Sign In With Google</button>
</div>
<div hidden$="[[!user]]">
<table>
<tr><th>photoURL</th> <td><img src="[[user.photoURL]]" alt=""></td></tr>
<tr><th>uid</th> <td>[[user.uid]]</td></tr>
<tr><th>displayName</th> <td>[[user.displayName]]</td></tr>
<tr><th>email</th> <td>[[user.email]]</td></tr>
<tr><th>emailVerified</th> <td>[[user.emailVerified]]</td></tr>
</table>
<button on-tap="signOut">Sign Out</button>
</div>
</template>
<script>
Polymer({
is: 'my-account',
signInWithGoogle: function() {
this.$.auth.signInWithPopup().then(function(response) {
this.userData.displayName = response.user.displayName;
this.userData.email = response.user.email;
this.$.authDocument.save('/users', response.user.uid);
}.bind(this));
},
signOut: function() {
this.$.auth.signOut();
}
});
</script>
</dom-module>

firebase-collection : input value only updates first keystroke

I have a master-detail scenario. I'm using paper-datatable by David Mulder for my user-list. Data is populated through firebase collection
When tapping a row, a paper-dialog pops up with the details of the selected user.
When trying to edit a field, updating at firebase stops after one keystroke.
What am I missing?
<dom-module id="user-list">
<template>
<style>
:host {
#apply(--layout-vertical);
}
#editDialog {
min-width: 500px;
}
</style>
<firebase-collection location="https://<FIREBASE_APP>.firebaseio.com/users" data="{{users}}"></firebase-collection>
<paper-dialog id="editDialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop>
<div>
<paper-input value="{{selectedUser.name}}" label="Name" class="flex"></paper-input>
<paper-input value="{{selectedUser.username}}" label="Username" class="flex"></paper-input>
</div>
<div class="buttons">
<paper-button dialog-confirm autofocus>Ok</paper-button>
</div>
</paper-dialog>
<paper-datatable id="datatable" selected-item="{{selectedUser}}" selectable on-row-tap="_onDetail" data="{{users}}">
<div no-results>
Loading or no more items...
</div>
<paper-datatable-column header="Name" property="name" type="String" sortable style="min-width: 160px"></paper-datatable-column>
<paper-datatable-column header="Username" property="username" type="String" sortable style="min-width: 40px"></paper-datatable-column>
</paper-datatable>
</template>
<script>
Polymer({
is: 'user-list',
behaviors: [
Polymer.NeonAnimatableBehavior
],
properties: {
type: String,
selectedUser: {
type: Object,
notify: true
},
users: {
type: Array,
notify: true
},
animationConfig: {
value: function() {
return {
'entry': {
name: 'fade-in-animation',
node: this
},
'exit': {
name: 'fade-out-animation',
node: this
}
}
}
}
},
_onDetail: function() {
var dialog = document.getElementById('editDialog');
if (dialog) {
dialog.open();
}
}
})
</script>
</dom-module>
It seems firebase-collection isn't currently meant to be used in this way, it's more of a view into a Firebase location with data that's in an array-like structure. Although with the exception that you can add/delete new items but not update existing ones. See https://elements.polymer-project.org/elements/firebase-element?active=firebase-collection.
That said, each item in the collection has a __firebaseKey__ property that you could use to directly update that item in firebase.

Polymer, issue with binding array to paper slider value

Here is example of the issue: Plunk
The initial value, 31, is not binding when changing the slider.
Array value 31 is seated on the initiation, but can not be reseated after change.
How to properly bind slider to the array?
<base href="http://polygit.org/polymer+:master/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<link href="paper-slider/paper-slider.html" rel="import">
<link href="google-chart/google-chart.html" rel="import">
<dom-module id="dynamic-chart">
<template>
Binded values:
<br>
arrayItem: {{arrayItem(rows.*, 0, 1)}}
<br>
arrayBase: {{arrayBase(rows.*)}}
<hr>
Jan slider:
<paper-slider min="1"
max="31"
value="{{rows.0.1}}"
pin
editable>
</paper-slider>
</template>
<script>
Polymer({
is: 'dynamic-chart',
properties: {
rows: {
type: Array,
notify: true,
},
},
//domReady:
attached: function() {
this.async(function() {
this.rows=[ ["Jan", 31],["Feb", 28],["Mar", 31] ];
console.log('domReady');
});
},
// first argument is the change record for the array change,
// change.base is the array specified in the binding
arrayItem: function(change, index, path) {
console.log('arrayItem');
return this.get(path, change.base[index]);
},
arrayBase: function(change) {
console.log('arrayBase');
return change.base;
},
});
</script>
</dom-module>
<dynamic-chart>
</dynamic-chart>
Update:
array-selector (simple example) element can be used for this task too.
You are trying to bind your array first element rows.0.1 which is a constant value, 31 to the value of the paper-slider.
What is happening that the arrayItem get notifies when its value change i.e !== 31.
What you should do is to bind the max value like this.
Plunkr
<base href="http://polygit.org/polymer+:master/components/">
<!--<base href="http://polygit.org/components/">-->
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
<link href="paper-slider/paper-slider.html" rel="import">
<link href="google-chart/google-chart.html" rel="import">
<dom-module id="dynamic-chart">
<template>
init value, 31, can't be binded back to arrayItem once the slider in changed:
<br>
<br> Binded values:
<br><i>the arrayItem get notifies when its value change i.e !== 31</i>
<br> arrayItem: {{arrayItem(rows.*, 0, 1)}}
<br> arrayBase: {{arrayBase(rows.*)}}
<h1>paper-slider 1</h1>
<div>Rows First Element: <span>{{rows.0.1}}</span> ==> Constant value </div>
<div>paper-slider Value: <span id="ps1Value"></span></div>
<paper-slider min="1" max="31" pin editable value="{{rows.0.1}}" id="ps1">
</paper-slider>
<!-- You need to bind the paper-slider max to the selected rows item-->
<!-- Changing the max value to {{rows.1.1}} rows second element -->
<h1>paper-slider 2</h1>
<div>Rows Second Element: <span>{{rows.1.1}}</span> ==> Constant value </div>
<div>paper-slider Value: <span id="ps2Value"></span></div>
<paper-slider min="1" max="{{rows.1.1}}" pin editable value="{{_value2}}" id="ps2">
</paper-slider>
</template>
<script>
Polymer({
is: 'dynamic-chart',
properties: {
rows: {
type: Array,
notify: true,
},
_value2: {
type: Number,
value:0,
observer: '_value2Changed'
}
},
// you can also use an obsersver instead of the addEventListener
_value2Changed: function(val) {
console.log("this is paper-slider #2 value "+ val);
},
ready: function() {
//events for paper slider #1
document.querySelector('#ps1').addEventListener('value-change', function(e) {
document.querySelector('#ps1Value').textContent = e.target.value;
});
//events for paper slider #1
document.querySelector('#ps2').addEventListener('value-change', function(e) {
document.querySelector('#ps2Value').textContent = e.target.value;
});
},
//domReady:
attached: function() {
this.async(function() {
//init value, 31, can't be seated back once the slider in changed:
this.rows = [
["Jan", 31],
["Feb", 28],
["Mar", 31]
];
console.log('domReady');
//console.log(this.rows);
});
},
// first argument is the change record for the array change,
// change.base is the array specified in the binding
arrayItem: function(change, index, path) {
console.log('arrayItem');
//console.log(change);
//console.log(index);
//console.log(path);
//console.log(this.get(path, change.base[index]));
// this.get(path, root) returns a value for a path
// relative to a root object.
return this.get(path, change.base[index]);
},
arrayBase: function(change) {
console.log('arrayBase');
return change.base;
},
});
</script>
</dom-module>
<dynamic-chart>
</dynamic-chart>
It will be better to have your rows as object instead of Array of objects,this way:
rows:{
type: Array,
notify: true,
value:function(){
return [
{"label":"Jan", max:31},
{"label":"Feb", max:28},
{"label":"Mar", max:31}
];
}
},

Resources