I've updated to simple-schema npm and installed autoform 6.0 however I seem unable to successfully generate forms for collections. I get this error Exception in template helper: TypeError: Cannot read property 'mergedSchema' of undefined and I have no idea what it is referring to since this is a new build so it shouldn't be referencing any old autoform or simple-schema packages.
Path: imports/ui/pages/candidate-registration/contact-information/contact-information.html
<template name="App_contactInformation">
{{#with profile}}
{{firstName}}
{{> quickForm collection=Profile id="updateProfile" type="update"}}
{{/with}}
{{/if}}
</template>
Path: imports/ui/pages/candidate-registration/contact-information/contact-information.js
import { Profile } from '/imports/api/profile/profile.js';
import './contact-information.html';
Template.App_contactInformation.onCreated(function () {
this.autorun(() => {
this.subscribe('private.profile');
});
});
Template.App_contactInformation.helpers({
profile() {
var user = Profile.findOne({userId: Meteor.userId()});
return user;
}
});
Path: imports/api/profile/server/publications.js
// All profile-related publications
import { Meteor } from 'meteor/meteor';
import { Profile } from '../profile.js';
Meteor.publish('private.profile', function() {
if (!this.userId) {
return this.ready();
}
return Profile.find({"userId": this.userId});
});
Make sure you are also using aldeed:collection2-core
and have attached your schema to your collection. For example...
Books.attachSchema(Schemas.Book);
Related
I'm making a fullstack app with vue3, axios using FormKit. For editing existing records I want to populate the input fields with the current data fetched from a mysql database. I stripped down the code to everything needed to display my problem, which in this code example is populating the FormKit input field with the lotnumber I fetched via the asynchronous function "getLotById". The lotnumber appears in the paragraph section but not in the input field. How can I properly delay the rendering of the FormKit element until the lotnumber has been fetched? Here's my code:
<script>
// import axios
import axios from "axios";
export default {
name: "LotEdit",
data() {
return {
lotnumber: this.lotnumber
}
},
props: {
lotid: Number
},
created: async function () {
await this.getLotById();
},
methods: {
// Get Lot By Id
async getLotById() {
try {
const response = await axios.get(`http://localhost:5000/lot/${this.$route.params.id}`);
this.lotnumber = response.data.lotnumber;
console.log(response.data);
}
catch (err) {
console.log(err);
}
},
}
};
</script>
<template>
<div>
<FormKit
type="text"
name="lotnumber"
label="lotnumber"
placeholder=""
validation="required"
:value="lotnumber"
/>
</div>
<div>
<p> Here the lotnumber appears: {{ lotnumber }}</p>
</div>
</template>
I suggest using a v-model on the FormKit input. Because it is two-way bound it means as soon as the async/await completes the data is populated on the template too. Something like...
<FormKit
v-model="lotnumber"
type="text"
name="lotnumber"
label="lotnumber"
placeholder=""
validation="required"
:value="lotnumber"
/>
Getting a little smarter I managed to solve the problem in the following way:
<script>
// import axios
import axios from "axios";
export default {
name: "LotEdit",
data() {
return {
lotnumber: this.lotnumber
}
},
props: {
lotid: Number
},
mounted: async function () {
const response = await this.getLotById();
const node = this.$formkit.get('lotnumber')
node.input(response.data.lotnumber, false)
},
methods: {
// Get Lot By Id
async getLotById() {
try {
const response = await axios.get(`http://localhost:5000/lot/${this.$route.params.id}`);
console.log(response.data);
return response;
}
catch (err) {
console.log(err);
}
},
}
};
</script>
<template>
<div>
<FormKit
type="text"
id="lotnumber"
name="lotnumber"
label="lotnumber"
placeholder=""
validation="required"
:value="lotnumber"
/>{{ lotnumber }}
</div>
</template>
Feel free to post any recommendations as I'm not a pro yet...
I'm also still figuring out how to handle controlled forms but I guess an alternative way to do it is with Form Generation
<script>
export default {
// ...
async setup() {
try {
const response = await axios.get(`http://localhost:5000/lot/${this.$route.params.id}`);
const schema = [
{
$formkit: "text",
label: "Lot Number",
value: response.data.lotnumber,
validation: "required",
},
];
} catch (err) {
console.log(err);
}
return { schema }
}
// ...
}
</script>
<template>
<FormKit type="form">
<FormKitSchema :schema="schema" />
</FormKit>
</template>
here is the adapter
In Ember Data, an Adapter determines how data is persisted to a backend data store. Things such as the backend host, URL format and headers used to talk to a REST API can all be configured in an adapter.
/* adapters/application.js */
import FirebaseAdapter from "emberfire/adapters/firebase";
export default FirebaseAdapter.extend({});
A Controller is routable object which receives a single property from the Route .. here is the controller
/* controllers/cars.js */
import Controller from "#ember/controller";
export default Controller.extend({
actions: {
deleteCar(id) {
this.get("store")
.findRecord("car", id, { reload: true })
.then(car => {
car.destroyRecord();
car.save();
//self.transitionToRoute("cars");
});
}
}
});
/* controllers/cars/edit.js */
import Controller from "#ember/controller";
export default Controller.extend({
actions: {
editCar: function(id) {
var self = this;
var make = this.get("model.make");
var model = this.get("model.model");
var year = this.get("model.year");
this.store.findRecord("car", id).then(function(car) {
car.set("make", make);
car.set("model", model);
car.set("year", year);
car.save();
self.transitionToRoute("cars");
});
}
}
});
/* controllers/cars/new.js */
import Controller from "#ember/controller";
export default Controller.extend({
actions: {
addCar: function() {
var self = this;
var rand = Math.floor(Math.random() * 10000 + 1);
var newCar = this.store.createRecord("car", {
id: rand,
make: this.get("carMake"),
model: this.get("carModel"),
year: this.get("carYear")
});
newCar.save();
self.transitionToRoute("cars");
}
}
});
In Ember Data, models are objects that represent the underlying data that your application presents to the user. Note that Ember Data models are a different concept than the model method on Routes, although they share the same name .. here is the model
/* models/cars.js */
import DS from "ember-data";
export default DS.Model.extend({
make: DS.attr("string"),
model: DS.attr("string"),
year: DS.attr("string")
});
In Ember, when we want to make a new page that can be visited using a URL, we need to generate a "route" using Ember CLI .. here is the routes
/* routes/cars.js */
import Route from "#ember/routing/route";
export default Route.extend({
model() {
return this.store.findAll("car", {
orderBy: "make"
});
}
});
/* routes/cars/edit.js */
import Route from '#ember/routing/route';
export default Route.extend({});
/* routes/cars/new.js */
import Route from "#ember/routing/route";
export default Route.extend({
model() {
return this.store.findAll("car");
}
});
/* routes/users.js*/
import Route from "#ember/routing/route";
import $ from "jquery";
export default Route.extend({
model: function() {
var url = "https://api.github.com/users";
return $.getJSON(url).then(function(data) {
return data.splice(0, 10);
});
}
});
The EmberRouter class manages the application state and URLs .. here is the router
/* router.js */
import EmberRouter from "#ember/routing/router";
import config from "./config/environment";
const Router = EmberRouter.extend({
location: config.locationType,
rootURL: config.rootURL
});
Router.map(function() {
this.route("cars", function() {
this.route("new");
this.route("edit", { path: "/edit/:car_id" });
});
this.route("users");
});
export default Router;
A template is used to create a standard layout across multiple pages. When you change a template, the pages that are based on that template automatically get changed. Templates provide standardization controls.
<!-- templates/users.hbs -->
<h1>Github Users</h1>
<ul>
{{#each model as |user|}}
<li>{{user.login}}</li>
{{/each}}
</ul>
<!-- templates/car.hbs -->
{{#link-to "cars.new"}}Create Car{{/link-to}}
<hr>
{{outlet}}
<h1>Cars</h1>
<ul>
{{#each model as |car|}}
<li>
{{car.year}} {{car.make}} {{car.model}} -
{{#link-to "cars.edit" car.id}}Edit{{/link-to}}
<button {{action "deleteCar" car.id}}>Delete</button>
</li>
{{/each}}
</ul>
<!-- templates/application.hbs -->
{{outlet}}
<!-- templates/cars/new.hbs -->
<form {{action "addCar" on="submit"}}>
<p>Make: {{input type="text" value=carMake}}</p>
<p>Model: {{input type="text" value=carModel}}</p>
<p>Year: {{input type="text" value=carYear}}</p>
<p>{{input type="submit" value="submit"}}</p>
</form>
<!-- templates/cars/edit.hbs -->
<form {{action "editCar" model.id on="submit"}}>
<p>Make: {{input type="text" value=model.make}}</p>
<p>Model: {{input type="text" value=model.model}}</p>
<p>Year: {{input type="text" value=model.year}}</p>
<p>{{input type="submit" value="Submit"}}</p>
</form>
run
Uncaught TypeError: Cannot read property 'initializedRelationships' of
undefined
https://i.stack.imgur.com/y7Ax0.png
here is my app drive link
The error disappears when I remove the findAll query inside model hook. Probably this would be an error with firebase config.
You missed entering the below config. Make sure you have all these variables inside your app/config/environment.js
var ENV = {
firebase: {
apiKey: "your-api-key",
authDomain: "YOUR-FIREBASE-APP.firebaseapp.com",
databaseURL: "https://YOUR-FIREBASE-APP.firebaseio.com",
projectId: "YOUR-FIREBASE-APP",
storageBucket: "YOUR-FIREBASE-APP.appspot.com",
messagingSenderId: "00000000000"
}
}
My app works fine with firebase. Please do follow the step by step approach from here
You have installed both stable and latest build versions of emberfire,
"emberfire": "^2.0.10",
"emberfire-exp": "^3.0.0-rc.1-4",
Which is not necessary. Install any one version.
if you are using ember-cli 3.12.0, when you are creating the firebase connection with your app by default "emberfire/adapters/firebase" will be imported automatical in adapters/application.js, which is not true.
`/* adapters/application.js */
import FirebaseAdapter from "emberfire/adapters/firebase";
export default FirebaseAdapter.extend({});`
go there and edit that import to "emberfire/adapters/firestore".
`import FirebaseAdapter from 'emberfire/adapters/firestore';
export default FirebaseAdapter.extend({
});`
and downgrade your "ember-source to : 3.10.0" in package.json
I'm working on something in Vue.js where I need to pass a value (symbol) that is coming from vue-router into a Firebase database query to retrieve the JSON object that matches that query. I can only do this via a v-for / v-if hack within the template. I know there must be a way to simply return this query within my script tags.
I have access to the database via the vuefire plugin.
<template>
<div>
<h3>Edit Crypto</h3>
<div v-for="crypto in getCryptos" :key="crypto[symbol]">
<div v-if="crypto.symbol === symbol">
{{ crypto.name }} - {{ crypto.symbol }}
</div>
</div>
<div>
{{ cryptoTest }}
</div>
</div>
</template>
dbCryptosRef is the database (image below) reference. getCrypto is the method I am trying to use to query the dabase. Below is the script tag within the same file. dbCryptosRef.equalTo(this.$route.params.symbol) simply returns the url for the firebase database, not as JSON object. What am I doing wrong?
<script>
import { mapGetters } from 'vuex'
import { dbCryptosRef } from '../firebaseConfig'
export default {
data()
{
return {
symbol: this.$route.params.symbol,
crypto: {},
cryptoTest: {}
}
},
computed: {
...mapGetters ([
'getCryptos'
])
},
methods: {
getCrypto: function()
{
this.cryptoTest = dbCryptosRef.equalTo(this.$route.params.symbol)
}
},
created() {
this.getCrypto();
}
}
</script>
You need to call value to get the data
getCrypto: function() {
this.cryptoTest = dbCryptosRef.equalTo(this.$route.params.symbol).once('value').then(snapshot => {
// do what you want with snapshot data
})
}
You can read more in Firebase document
I am having two questions:
1) I want to use Meteor 1.5 Dynamic Import for Blaze but all the examples and tutorials are given for React. So I am confused how exactly it can be used . Can anyone give examples of it.
2) I am using packages from atmospherejs.com like amcharts which I only need at Admin Dashboard side. How to dynamically import them?
Thanks in Advance!
UPDATE(Solution):
Below is homepage.html (parent template)
<template name="homepage">
Homepage Content
{{> Template.dynamic template=content}}
</template>
login.html (child template)
<template name="login">
You're logged in!
</template>
login.js
import '../homepage/homepage.js';
import './login.html';
API = function () {
BlazeLayout.render("homepage",{content: 'login'});
}
export { API }
main.js
LoadLogin = function () {
import('/imports/modules/common/login/login.js').then(function (api) {
api.API();
})
}
/lib/route.js
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
FlowRouter.route('/', {
name: 'homepage',
action() {
LoadLogin();
}
});
I am developing my own admin panel, Meteor Candy, to be driven by dynamic imports, so I am happy to share how I got it working.
First, we have the view.html:
<template name="admin">
Admin
</template>
Second, we have our JS logic:
import { Template } from 'meteor/templating';
import { Meteor } from 'meteor/meteor';
import { Blaze } from 'meteor/blaze';
import './view.html';
API = {}
API.render = function () {
Blaze.render(Template.admin, document.body);
}
export { API }
Finally, we just need to import that code and trigger our Template to be rendered into the page:
openAdmin = function () {
import('./imports/admins').then(function (api) {
api.render()
})
}
Once something runs the openAdmin() function, the templates will be imported from the server and the render function will be called.
The basic technique for dynamically importing modules in Meteor 1.5 using Blaze is as follows:
Template.theTemplate.events({
'click button'(event, instance) {
import("foo").then(Foo => {
console.log(Foo);
});
}
});
Make sure you take a close look at how your module is then imported, because apparently some refactoring may be needed when calling it in your code. For example, using "zxcvbn":
WAS
const result = zxcvbn(pwd);
IS
const result = zxcvbn.default(pwd);
It is pretty straight forward using example link https://github.com/thesaucecode/meteor-amcharts-example/blob/master/client/example2.js, you just have to write the code inside Template.MYTEMPLATE.onRendered(function(){});
On top of that you can use var chart as reactive-var.
I'm trying to build a very simple Meteor app. I have implemented all CRUD. But my problem is when I have use publish and then subscribe, no data is returned. My code is given below:
imports\api\tasks\tasks.js
import { Mongo } from 'meteor/mongo';
import { Meteor } from 'meteor/meteor';
TasksSchema = new SimpleSchema({
title: {
type: String
},
owner: {
type: String
}
});
export const Tasks = new Mongo.Collection('tasks', { schema: TasksSchema });
if (Meteor.isServer) {
Meteor.publish('task.list', function() {
return Tasks.find({ owner: this.userId });
});
}
imports\ui\components\home\home.js
import { Tasks } from '/imports/api/tasks/tasks.js';
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating'
import { ReactiveDict } from 'meteor/reactive-dict';
import './home.html';
if (Meteor.isClient) {
Template.home.onCreated(function bodyOnCreated() {
Meteor.subscribe('task.list');
});
Template.home.helpers({
tasks() {
let userId = Meteor.userId();
return Tasks.find({ owner: userId }, { sort: { updatedAt: -1 } });
}
});
}
imports\ui\components\home\home.html
<!-- here nothing is shown,although I have data -->
{{#each task in tasks }}
{{task.title}}
{{/each}}
Any suggestion? Thanks in advance.
Instead of {{task.title}} try {{title}} and also check in browser console Task.find({}).fetch() and see whether you can see records or not.
Its probably because your subscription isn't ready to be used on client.
What you have to do is wrap your each code in subscriptionsReady function like below:
{{#if Template.subscriptionsReady}}
{{#each task in tasks }}
{{task.title}}
{{/each}}
{{else}}
<p>Loading...</p>
{{/if}}
Above should work.
You can check this link for more information of how to use subscriptionsReady