Integrating Uniforms in Meteor app with React JS
Sep 04, 2019 · 4 minutes
While I was trying to implement uniforms
, ReactJS Component package for handling form, in one of my project which use Meteor Framework and ReactJS as view engine, integration was tricky and most document are outdated. After few attempt, I solve it and decided to write a blog.
In this article, without wasting time, I will go through step by process to install uniforms and implement it.
So let’s start, first uniforms has support for popular css framework like bootstrap, semantic-ui etc. It can also be implemented without using any of those css framework. But for this article we will use semantic ui. So let’s go step by step:
Installing Required Dependencies
meteor npm i --save uniforms
meteor npm i --save uniforms-semantic
meteor npm i --save uniforms-bridge-simple-schema-2
meteor npm i --save simpl-schema
Use
simpl-schema
rather thenaldeed/simple-schema-js
which won’t work but is suggested by other old guide.
Now, we will create a simple mongo collection in import/api
folder. Let’s sayProducts.js
which will contain a simple collection declaration statement and a simple schema for the collection.
Creating Simple Schema & Collection
import { Mongo } from "meteor/mongo";
import SimpleSchema from "simpl-schema";
import { Tracker } from "meteor/tracker";
Meteor.methods({
"products.insert": function(data) {
Products.insert({ ...data, createdAt: Date.now() });
}
});
Products = new Mongo.Collection("products");
ProductSchema = new SimpleSchema(
{
productName: {
type: String
},
price: {
type: String,
optional: true
},
color: {
type: String,
optional: true
},
brand: {
type: String,
optional: true
},
productDescription: {
type: String,
max: 400
},
productImage: {
type: String,
optional: true
},
productDescription: {
type: String,
optional: true
},
productCategory: {
type: String,
optional: true,
allowedValues:["Electronics", "Automobile"]
},
productYear: {
type: Number,
optional: true
},
priceNegotiable: {
type: Boolean,
optional: true
},
conditions: {
type: String,
optional: true
},
userFor: {
type: Number,
optional: true
},
homeDeliveryOptions: {
type: String,
optional: true,
allowedValues:["Yes", "No"]
}
},
{ tracker: Tracker }
);
Products.attachSchema(ProductSchema);
export { ProductSchema, Products }
In the above code, tracker:Tracker
is passed toSimpleSchema
constructor. Moreover,attachSchema
prototype is used from Products
object to attached schema to collection declaration. We are done in api/import
folder. Also, don’t forget to export the schema and collection.
Wherever uniforms AutoForm component is used, it is necessary to import
` uniforms-bridge-simple-schema-2
package.
Let, create a ` ProductForm
component inimports/ui
folder so that.
Creating a Simple Form Component
import React from "react";
import { Meteor } from "meteor/meteor";
import AutoForm from "uniforms-semantic/AutoForm";
import TextField from "uniforms-semantic/TextField";
import LongTextField from "uniforms-semantic/LongTextField";
import SelectField from "uniforms-semantic/SelectField";
import NumField from "uniforms-semantic/NumField";
import SubmitField from "uniforms-semantic/SubmitField";
import { Form } from "semantic-ui-react";
import "uniforms-bridge-simple-schema-2";
import { ProductSchema } from "../../api/products.js";
export default function ProductForm({ model = undefined }) {
function submit(data, formRef) {
Meteor.call("products.insert", data, err => {
if (err) {
console.log(err);
// Necessary code for handling error is written here.
return;
} else {
// this code will clear all the value in the form.
formRef.clear;
// Necessary code after success is written here.
return;
}
});
}
return (
<AutoForm
ref={ref => {
fRef = ref;
}}
schema={ProductSchema}
onSubmit={data => submit(data, fRef, modal)}
>
<Form.Field>
<Form.Group widths="equal">
<TextField
name={"productName"}
showInlineError={true}
placeholder="Enter Product Name"
/>
<TextField
name={"price"}
showInlineError={true}
placeholder="Enter Product Price"
/>
</Form.Group>
<Form.Group widths="equal">
<TextField
name={"color"}
showInlineError={true}
placeholder="Enter Product color"
/>
<TextField
name={"brand"}
showInlineError={true}
placeholder="Enter Product brand"
/>
</Form.Group>
<Form.Group widths="equal">
<LongTextField
name={"productDescription"}
showInlineError={true}
placeholder="Enter Product Description"
/>
</Form.Group>
</Form.Field>
<Form.Field>
<Form.Group widths="equal">
<SelectField name={"productCategory"} showInlineError={true} />
<TextField
name={"productYear"}
showInlineError={true}
placeholder="Enter manufactured year"
/>
</Form.Group>
</Form.Field>
<Form.Field>
<Form.Group widths="equal">
<LongTextField
name={"conditions"}
showInlineError={true}
placeholder="Product Condition"
/>
</Form.Group>
</Form.Field>
<Form.Field>
<Form.Group widths="equal">
<NumField name={"userFor"} showInlineError={true} />
<SelectField name={"homeDeliveryOptions"} showInlineError={true} />
</Form.Group>
</Form.Field>
<SubmitField />
</AutoForm>
);
}
In the above code, we have used AutoForm
component. As a children, we have implement some component from semantic-ui-react
(might need to install it if you haven’t :D) and some component form uniforms-semantic
to generate a decent looking form. Furthermore, we have passed onSubmit function to user input values when user submit a
form.
Passing
showInLineError
props as true will show error just below the relevant form input field.
Let’s look at the submit
function, as it receive two parameter, data & formRef. Moving forward, early in Products.js
we have also declared Meteor method which save data to db which is define as product.insert
just after declaring mongo collection. Now, we are going to call
the same method as passing the data object.
function submit(data, formRef) {
Meteor.call("products.insert", data, err => {
if (err) {
console.log(err);
// Necessary code for handling error is written here.
return;
} else {
// this code will clear all the value in the form.
formRef.clear;
// Necessary code after success is written here.
return;
}
});
}
formRef.clear
is used to clear the form after successfully submission. Also, there are other way to handle form reset it is just one way.
In conclusion, schema and its validation rules need define the error message and they can be customized.
For further reading refer simpl-scheme
docs.