Polymer 2.0 + firebase can't update properly - firebase

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)

Related

vee-validate 4.7 | VueJS 3 | Single input field validate

I am using VueJS 3 and want to validate my step by step screen with single OR multiple input fields and want to check is he field valid or not and based on that I have to enable next button.
For validation I am using vee-validate plugin 4.7.3.
In my case I also do not want to use the form tag if possible. As my field is independent so no need to use form.
But as I search and read the comments of the package owner and mentioned that need to use Form so I used it but I just want to check the field validation as I have to show/hide the next button.
Component.vue
<template>
<Form :validateOnModelUpdate="true">
<Field name="mobile" as="input" :rules="mobileRules" v-model="mobile" />
</Form>
// Want to display button if the validation match
// Out side of the form
<button class="btn btn-default" v-if="IF_VALID" > Next </button>
</template>
<script>
import * as Yup from 'yup';
export default {
data(){
return {
mobile: '',
mobileRules: Yup.string().required().min(6)
}
}
}
</script>
If is there anyway to access the meta of the Field then may be that will be helped me.
Thanks.
I have tried to user UseField/useIsFieldValid but it shows me error that the
field with name mobile was not found
Also tried to use ref on the field but I can't able to access the meta of the Field
I have fixed it by using following code change:
For the field level validation need to code like this.
You can access field meta data in your component anywhere out of the Form
As per the owner comment if need to access this type of data out of the component need to achieve like this.
Owner Comment on Discussion
<template>
<div>
<form > <!-- This is simple HTML form -->
<input class="form-control" type="text" name="mobile" v-model="mobile" placeholder="000-0000-000">
<span class="text-danger" v-if="mobileErr">{{ mobileErr }}</span>
</form>
<button v-if="mobileMeta.valid"> Next </button>
</div>
</template>
<script>
import * as Yup from 'yup';
import { useField } from 'vee-validate';
export default {
setup(){
const mobileRules = Yup.string().required('Required').min(10, 'Must be 10 digits');
const { meta: mobileMeta, value: mobile, errorMessage: mobileErr} = useField('mobile', mobileRules);
return {
mobileMeta,
mobile,
mobileErr
}
},
data(){
return {
steps: '',
loading: false
}
},
created(){
},
methods:{
methodOne () {
// Some code to perform
},
methodTwo () {
// Some code to perform
}
}
}
</script>
Hopefully it will helps to others who want to perform step by step form and need to valid the field one by one.
Thanks.

Pushing data to object in different component using POST

TL;DR I want to show submitted posts instantly instead of having to refresh my page
Using the Wordpress REST API I am able to create a new post without any issue. The post is being displayed as soon as the page refreshes, so what I want to do is update the posts object in my Hello.vue file as soon as I create that post so I don't need to refresh to show my newest posts.
I'm not really sure where to start - I've removed all of the experiments I've done so far (importing Post in Create, defining props, pushing to an array, reading about object reactivity on the official Vue documentation, nothing helped).
My App.js consists of the <router> object which shows Hello.vue and a component called Create which displays the Create.vue component. This is how my app currently looks like:
My App.vue file:
<template>
<div id="app">
<section class="posts">
<router-view></router-view>
<create></create>
</section>
</div>
</template>
<script>
import Create from '#/components/Create.vue'
export default {
name: 'app',
components: {
Create
}
}
</script>
<style lang="scss">
#import '../src/assets/styles/style.scss'
</style>
My Hello.vue which displays all the posts:
<template>
<div>
<section class="posts__Feed">
<ul class="posts__List">
<post v-for="item in posts" :item="item" :key="item.id"></post>
</ul>
</section>
</div>
</template>
<script>
var postsUrl = '/wp-json/wp/v2/posts/'
import Post from '#/components/Post.vue'
export default {
name: 'hello',
props: ['responseData'],
components: {
Post
},
data () {
return {
posts: []
}
},
beforeCreate () {
this.$http.get(postsUrl).then((response) => {
this.posts = response.data
})
}
}
</script>
And finally, the Create.vue file which creates the post:
<template>
<div>
<section class="posts__Create">
<form class="posts__CreateForm" v-on:submit="createPosts">
<div class="posts__CreateFormWrapper" v-bind:class="{ 'is-Loading': loading }">
<p>
<input v-model="formInfo.title" type="text" name="title" id="title" placeholder="Name" :disabled="formSent">
</p>
<p>
<textarea v-model="formInfo.content" name="content" id="content" cols="20" rows="10" maxlength="140" placeholder="Message" :disabled="formSent"></textarea>
</p>
<p>
<button :disabled="formSent">Send</button>
</p>
</div>
</form>
</section>
</div>
</template>
<script>
var postsUrl = '/wp-json/wp/v2/posts/'
export default {
name: 'create',
data () {
return {
formInfo: [],
responseData: [],
loading: false,
formSent: false
}
},
methods: {
createPosts (e) {
e.preventDefault()
var info = this.formInfo
// Check if fields are empty
if (this.formInfo.title && this.formInfo.content) {
this.loading = true
// POST
this.$http.post(postsUrl, info).then((response) => {
this.formSent = true
this.loading = false
// get body data
this.responseData = response.data
})
}
} // EOF createPosts
}
}
</script>
Any help would be much appreciated!
I ended up using an event bus as suggested by wotex. First, I've createad a file called bus.js with the below code:
import Vue from 'vue'
export const EventBus = new Vue()
Next, import bus.js to both .vue layouts using:
import { EventBus } from '#/bus.js'
Now emit the event as soon as a new post is created (this is sitting in my axios POST request inside the Create.vue file):
EventBus.$emit('newPost', this.responseData)
And finally, check if the event has happened on the other end (my Hello.vue file):
EventBus.$on('newPost', function (postData) {
Thanks for pointing me in the right direction!

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.

Calling Meteor methods in React components

Currently I'm working on a project based on Meteor as back end and React as front end. I really enjoyed simplicity untill I removed insecure package and have to deal with Meteor methods. Right now I need to perform a basic insert operation and I'm just stucked!
I have a form as component (in case eventually I'd like to use this form not only for inserting items but for editing those items as well) and here's my code for this form:
AddItemForm = React.createClass({
propTypes: {
submitAction: React.PropTypes.func.isRequired
},
getDefaultProps() {
return {
submitButtonLabel: "Add Item"
};
},
render() {
return (
<div className="row">
<form onSubmit={this.submitAction} className="col s12">
<div className="row">
<div className="input-field col s6">
<input
id="name"
placeholder="What"
type="text"
/>
</div>
<div className="input-field col s6">
<input
placeholder="Amount"
id="amount"
type="text"
/>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<textarea
placeholder="Description"
id="description"
className="materialize-textarea">
</textarea>
</div>
</div>
<div className="row center">
<button className="btn waves-effect waves-light" type="submit">{this.props.submitButtonLabel}</button>
</div>
</form>
</div>
);
}
});
This chunk of code is used as a form component, I have a prop submitAction which I use in let's say add view:
AddItem = React.createClass({
handleSubmit(event) {
event.preventDefault();
const
name = $('#name').val(),
amount = $('#amount').val(),
description = $('#description').val();
Items.insert(
{
name: name,
range: range,
description: description,
createdAt: new Date(),
ownerId: Meteor.userId()
},
function(error) {
if (error) {
console.log("error");
} else {
FlowRouter.go('items');
};
}
);
},
render() {
return (
<div className="row">
<h1 className="center">Add Item</h1>
<AddItemForm
submitButtonLabel="Add Event"
submitAction={this.handleSubmit}
/>
</div>
);
}
});
As you can see I directly grab values by IDs then perform insert operation which works absolutely correct, I can even get this data displayed.
So now I have to remove insecure package and rebuild the whole operation stack using methods, where I actually stucked.
As I understand all I should do is to grab same data and after that perform Meteor.call, but I don't know how to pass this data correctly into current method call. I tried considering this data right in the method's body which doesn't work (I used the same const set as in AddItem view). Correct me if I'm wrong, but I don't think this method knows something about where I took the data (or may be I don't really get Meteor's method workflow), so by this moment I ended up with this code as my insert method:
Meteor.methods({
addItem() {
Items.insert({
name: name,
amount: amount,
description: description,
createdAt: new Date(),
ownerId: Meteor.userId()
});
}
});
and this is how I changed my handleSubmit function:
handleSubmit(event) {
event.preventDefault();
const
name = $('#name').val(),
amount = $('#amount').val(),
description = $('#description').val();
Meteor.call('addItem');
},
Also I tried declaring method like this:
'addItem': function() {
Items.insert({
// same code
});
}
but it also didn't work for me.
Again, as I understand the problem isn't about data itself, as I wrote before it works just right with insecure package, the problem is how the heck should I get this data on the server first and right after that pass this to the client using methods (also console gives no even warnings and right after I submit the form, the page reloads)?
I've already seen some tutorials and articles in the web and didn't find desicion, hope to get help here.
You can add your data as parameters in your Meteor call function. You can also add a callback function to check on the success of the call.
handleSubmit(event) {
event.preventDefault();
const
name = $('#name').val(),
amount = $('#amount').val(),
description = $('#description').val();
Meteor.call('addItem', name, amount, description, function(err, res) {
if (err){
console.log(JSON.stringify(err,null,2))
}else{
console.log(res, "success!")
}
});
},
In your Meteor methods:
Meteor.methods({
addItem(name, amount, description) {
var Added = Items.insert({
name: name,
amount: amount,
description: description,
createdAt: new Date(),
ownerId: Meteor.userId()
});
return Added
}
});

How to pass parameter data between templates in meteor flowlayout flowrouter

I have a template called : Orders which shows my orders collection of images :
{{#each images}}
<div class="images">
<img class="image" src="{{this.url }}" />
</div>
{{/each}}
No I want another tempate called order to show me only one item from collection that I click on: I try doing this way: 1. orders.js events for click on image:
"click .image": function() {
Images.find({_id:this._id});
and orders.html:
<img class="image" src="{{this.url }}" />
I also have routes.js :
FlowRouter.route("/orders", { **this part works fine**
action: function(){
FlowLayout.render("layout",{top:"orders", main:"test"});
}
FlowRouter.route('/order/', { **How do I do this part ????????**
action: function(){
FlowLayout.render("layout",{top:"order",data:image});
}
I used a dynamic layout template to show orders which shows fine.
How do I set the single order html , route and render ????
To answer your question:
Beginning by your route, you should pass the id parameter in the path like that :
FlowRouter.route('/order/:imageId', {
action: function() {
FlowLayout.render("layout",{ top: "order", main: "test" });
}
});
Looking at the rendering on order.html file which contains the template order, something like:
<template name="order">
{{#with image}}
<!-- whatever you want to do -->
<img src="{{url}}" />
{{/with}}
</template>
This template uses order.js with a subscription to your collection for one image only and a helper called image which look for the parameter imageId you transmitted in your route via the function FlowRouter.getParam:
Template.order.onCreated(function() {
var imageId = FlowRouter.getParam('imagedId');
if ( imageId !== undefined ) {
Meteor.subscribe('oneImage', imageId);
}
}
Template.order.helpers({
image: function() {
var imageId = FlowRouter.getParam('imagedId');
if ( imageId !== undefined ) {
return Images.findOne({ _id: imageId });
}
}
}
And to conclude, server side, you shall do a publication:
Meteor.publish('oneImage', function(imageId) {
return Images.findOne({ _id: imageId });
}
Following this way, you don't need anymore your event click .image and you optimized your performance! ;)
Btw on orders.html in your {{#each}} loop, you don't need to write {{this.url}} nor {{this._id}}, {{url}} and {{_id}} are fine ;)
To retrieve request parameter you can use:
FlowRouter.current().route._params.keys.id

Resources