"Uncaught TypeError: Cannot read property 'push' of null" with Polymer 3 and polymerfire3 - firebase

I'm working in a project with Polymer 3 and polymerfire3.
Right now I have been able to use firebase-auth element successfully. But now that I'm trying to use the firebase-query element I get this on the console Uncaught TypeError: Cannot read property 'push' of null
This is my code
import { PolymerElement, html } from '#polymer/polymer/polymer-element.js';
import './shared-styles.js';
import 'polymerfire3/firebase-auth.js';
import 'polymerfire3/firebase-query.js';
class PerfilView extends PolymerElement {
static get properties() {
return {
user: Object,
uid: String,
data: {
type: Object,
observer: 'dataChanged'
}
};
}
static get template() {
return html`
<firebase-auth
id="auth" user="{{user}}">
</firebase-auth>
<firebase-query
log
id="query"
app-name="morse"
path="/notes/"
data="{{data}}">
</firebase-query>
<div class="card">
<div id="notes">
<ul id="notes-list">
<template is="dom-repeat" items="{{data}}" as="note">
<li>
<p class="content">{{note}}</p>
</li>
</template>
</ul>
<paper-input value="{{inputP::input}}" label="Take a note.."></paper-input>
<div id="notes-controls">
<paper-button id="add" on-tap="add">Add</paper-button>
</div>
</div>
</div>
`;
}
add() {
this.$.query.ref.push({
content: this.inputP
});
}
}
window.customElements.define('perfil-view', PerfilView);
Does it have something to do with the polymerfire3 elements?

You will need to add polymer-document in order to add a record. Additional to your code, something like:
<firebase-document
id="document"
app-name="morse"
path="/notes/[[key]]"
data="{{edata}}">
</firebase-document>
and pushing new data may look like ;
add() {
var key = firebase.database.ref('notes').push().key;
this.set('edata', this.inputP);
this.set('key', key);
// this new Note will be syncronised upon new key and edata properties defined. Here firebase-document will keep sysnronised with edata and path.
}

firebase-query element is basically utilized for -
combining the given properties into query options that generate a
query, a request for a filtered, ordered, immutable set of Firebase
data
Here is further to read up on.
I think, what you're trying to do, can simply be achieved as follows -
add(noteData) {
let newNoteRef = firebase.app().database().ref('notes').push();
return newNoteRef.set(noteData).then(() => {
console.log(`a new note successfully added.`);
});
}
Upon successful data upsert firebase-query will automatically update data bound-variable to reflect the new list.

Related

how to find document in mongodb with its id passed in textbox?

I am learning mongodb with meteor js so dont have much knowledge of both mongodb and meteor.
Below is the js code:
import { Template } from 'meteor/templating';
import { Dbs } from '../lib/collections.js';
import './main.html';
Template.body.helpers({
/*temp1:[
{text:'my data1'}'
{text:'my data1'}
]*/
dbs(){
return Dbs.find({'user_id':'p123'});
}
});
Basically i just want to pass user id in a textbox and based on it,i want to display the other details of user.In above code i am passing it manually and its working.anyone suggest me what should i do here ?
You can attach to the template instance a ReactiveVar that you will update with an event.
Then use it inside the helper, so the helper will re-execute everytime the value change:
Template.myTemplate.onCreated(function() {
this.currentTextBox = new ReactiveVar();
});
Template.myTemplate.events({
"keyup .js-my-textbox"(event, instance) {
// This event is executed when you type in an input with the class "js-my-textbox"
instance.currentTextBox.set(event.target.value);
},
});
Template.myTemplate.helpers({
dbs() {
const instance = Template.instance();
return Dbs.find({'user_id': instance.currentTextBox.get() });
},
});
EDIT:
Example of what could be the html part:
<template name="myTemplate">
<input type="text" placeholder="Search" class="js-my-textbox">
{{#each db in dbs}}
<-- Do what you want, example: -->
<p>{{db.myField}}</p>
{{/each}}
</template>
First You Create Event Function Template.body.events({}) to access text .Then store variable to use Meteor Session. Then Variable easily access helpers.If session changes variable will be changed.

Vue.js 2 with Firebase Crud example

I'm struggling to edit a single item with vue and firebase.
My edit page url receives item's id.
So what I want is to load this single item from firebase.
Edit it and save it back into firebase.
I use vue version 2 and vuefire.
I'm stuck at loading a single item from firebase and displaying it in a form.
Here is what I've got so far:
<template>
<div>
<h1>Item: {{ item.name }}</h1>
<label>Name</label>
<input type="text" value="" name="hive-name"/>
</div>
</template>
<script>
import { db } from '../firebase';
export default {
data() {
return {
id: this.$route.params.id,
item: {},
}
},
firebase() {
return {
items: db.ref('items'),
item: db.ref('items/' + this.id),
}
},
methods: {
updateitem() {
this.$firebaseRefs.item.push(this.item);
},
},
}
</script>
according to VueFire in Github (https://github.com/vuejs/vuefire):
To delete or update an item you can use the .key property of a given object. But keep in mind you have to remove the .key attribute of the updated object:
updateItem: function (item) {
// create a copy of the item
item = {...item}
// remove the .key attribute
delete item['.key']
this.$firebaseRefs.items.child(item['.key']).set(item)
}
Please, note that you have to use "item.set" instead of "item.push".
"push" would create a new item instead of updating it.

Push data to Firebase via polymerfire/firebase-query element

I'm a little stuck trying to push data on demand to a Firebase database using the polymerfire polymer element. I have a data binding inside a DOM element and it works flawlessly for registers that already exists. My real question is how to create new registers with unique id?
//firebase query for a specific path and a data binding
<firebase-query
id="query"
app-name="testApp"
path="/[[uid]]/messages"
data="{{data}}">
</firebase-query>
//dom repeat for each item inside the data binding
<template is="dom-repeat" items="{{data}}">
<div class="card">
<p>[[item.text]]</p>
</div>
</template>
If I modify the template to have an iron-input and a 2 way data binding, this update the register at ease and no problem in Firebase.
<template is="dom-repeat" items="{{data}}">
<div class="card">
<input is="iron-input" bind-value="{{item.text}}">
</div>
</template>
The real tricky part is how to push a new object (message) to Firebase with a unique id, something like "lasdjlkadj1978kld"?
//firebase estructure
{
"uid" : {
"messages" : {
"message1" : {
"message" : "some text",
"timestamp" : "some date"
},
"message2" : {
"message" : "some text",
"timestamp" : "some date"
}
...
...
}
}
}
I have tried updating the "data" object via JS but its only modified locally...
I'm not sure I understand your question correctly.
How to create new registers with unique id?
You can use firebase-document that provide save method that take 2 arguments parentPath and key (just leave the key).
<firebase-document id='document'
data='{{data}}'>
</firebase-document>
<script>
Polymer({
saveMessage: function () {
// path = /<uid>/messages in your case
this.$.document.save(path).then(function () {
// after document saved, path will be changed to the new ref
// any change of data will sent back up and stored
});
}
});
</script>
I had tried updating the "data" object via js but its only modified
locally...
How you update the data, Did you use this.set?

React + Meteor keyed object warning

How do I get rid of this warning? If I delete task.created there is no warning. Can't figure this one out. See my code example below:
Warning: Any use of a keyed object should be wrapped in React.addons.createFragment(object) before being passed as a child.
ShowAllPosts = React.createClass({
mixins: [ReactMeteorData],
getMeteorData() {
// This function knows how to listen to Meteor's reactive data sources,
// such as collection queries
return {
// Returns an array with all items in the collection
tweets: Posts.find().fetch().reverse()
}
},
render() {
var showHTML = this.data.posts.map(function (task) {
return (
<div key={task._id}>
<img className="profile-pic" src="images/puppy.jpeg" />
{task.content}
<br />
Date: {task.created}, Get Link, id: {task._id}
<hr />
</div>
);
});
return (
<ul>
<hr />
{/* Access the data from getMeteorData() on this.data */}
{ showHTML }
</ul>
);
}
});
I assume that task.created is a Date object.
React isn't casting dates to strings automatically, so you need to write something like {task.created.toString()} or use package like moment to format your date.

How do I access one 'sibling' variable in a meteor template helper when I am in the context of another?

How do I access one 'sibling' variable in a meteor template helper, when I am in the context of another? I want to determine whether the user that is logged in and viewing the page is the same user that posted the ride offering, so that I can hide or show the "bid" button accordingly.
For example, here is my template (html) file:
<!-- client/views/ride_offers.html -->
<template name="RideOfferPage">
<p>UserIsOwner:{{UserIsOwner}}</p>
{{#with CurrentRideOffer}}
{{> RideOffer}}
{{/with}}
</template>
<template name="RideOffer">
<div class="post">
<div class="post-content">
<p>Details, Author: {{author}}, From: {{origin}}, To: {{destination}}, between {{earliest}} and {{latest}} for {{nseats}} person(s). Asking ${{price}}.
<button type="button" class="btn btn-primary" >Bid</button><p>
<p>UserIsOwner:{{UserIsOwner}}</p>
</div>
</div>
</template>
And here is my JavaScript file:
Template.RideOfferPage.helpers({
CurrentRideOffer: function() {
return RideOffers.findOne(Session.get('CurrentOfferId'));
},
UserIsOwner: function() {
return RideOffers.find({_id: Session.get('CurrentOfferId'), userId: Meteor.userId()}).count() > 0;
}
});
In the "RideOffer" template, I am able access the variables author, origin, ..., price. But I am unable to access the boolean UserIsOwner. I am, however, able to access the boolean UserIsOwner in the "RideOfferPage" template.
Does anyone know how I can access the boolean UserIsOwner in the "RideOffer" template?
Cheers,
Put the userIsOwner function outside the helper as an anonymous function and then call it from both templates.
Template.RideOfferPage.helpers({
CurrentRideOffer: function() {
return RideOffers.findOne(Session.get('CurrentOfferId'));
},
UserIsOwner: checkUserIsOwner()
});
Template.RideOffer.helpers({
UserIsOwner: checkUserIsOwner()
});
checkUserIsOwner= function() {
return RideOffers.find({_id: Session.get('CurrentOfferId'), userId: Meteor.userId()}).count() > 0;
}
There are several ways to do what you're asking.
In your particular example you are not asking about siblings, but about parents, since the RideOfferPage template renders the RideOffer template. You can access variables in the parent data context (but not helpers) like so:
<template name="RideOffer">
<div class="post">
<div class="post-content">
<!--
other stuff
-->
<p>UserIsOwner:{{../UserIsOwner}}</p>
</div>
</div>
</template>
In other cases, you may have a template being rendered as a sibling of this one. In that case, you can't actually know what the sibling is until the template is actually on the page; however, you can find it in the rendered callback:
Template.foo.rendered = function() {
var current = this.firstNode;
var next = $(currentItem).next(); // or .prev()
if (next.length) {
nextData = Spark.getDataContext(next[0]);
}
// Do something with nextData
};
Finally, you can get the parent context of any rendered DOM element by repeatedly iterating through its parents. This isn't super efficient but I've used it in places where there is extensive drag and drop with DOMFragments moving around on the page:
Template.bar.events = {
"click .something": function(e) {
var target = e.target;
var context = Spark.getDataContext(target);
var parentContext = context;
while (parentContext === context) {
parentContext = Spark.getDataContext(target = target.parentNode);
}
// Do something with parentContext
}
};
I'm curious to know if there is a better way to do the last thing, which may potentially have to iterate through many DOM elements. In any case, you may want to check out my meteor-autocomplete package for this and other cool tricks.

Resources