Giter Club home page Giter Club logo

meteor-wizard's Introduction

AutoForm Wizard

AutoForm Wizard is a multi step form component for AutoForm.

Installation

$ meteor add forwarder:autoform-wizard

Upgrade notice

Upgrading to 0.7.*

Iron router support has been moved to a separate package. See the Using routers section to see how to enable it.

Dependencies

  • AutoForm versions 5.

Example

A running example can be found here: http://autoform-wizard.meteor.com

The source code of the example app can be found on Github. https://github.com/forwarder/meteor-wizard-example

Basic usage

Create templates for the wizard

<template name="basicWizard">
  {{> wizard id="basic-wizard" steps=steps}}
</template>

Define the steps in a template helper

Schema = {};
Schema.information = new SimpleSchema(...);
Schema.confirm = new SimpleSchema(...);

Template.basicWizard.helpers({
  steps: function() {
    return [{
      id: 'information',
      title: 'Information',
      schema: Schema.information
    },{
      id: 'confirm',
      title: 'Confirm',
      schema: Schema.confirm,
      onSubmit: function(data, wizard) {
        // submit logic
      }
    }]
  }
});

Custom step templates

If you need more flexibility in your forms, you can define your own templates to be used for the steps.

Define your templates and include AutoForm

<template name="information">
  {{> quickform id="information-form" doc=step.data schema=step.schema}}
</template>

or

<template name="confirm">
  {{#autoForm id="confirm-form" doc=step.data schema=step.schema}}

    {{> afQuickField name="acceptTerms"}}

    {{> wizardButtons}} /* this will render back, next and confirm buttons */

  {{/autoForm}}
</template>

Configure steps

Template.basicWizard.helpers({
  steps: function() {
    return [{
      id: 'information',
      title: 'Information',
      template: 'information',
      formId: 'information-form',
    },{
      id: 'confirm',
      title: 'Confirm',
      template: 'confirm',
      formId: 'confirm-form',
      onSubmit: function(data, wizard) {
        // submit logic
      }
    }]
  }
});

Component reference

Wizard configuration

The following attributes are supported:

  • id: Required. The id used to identify the wizard.
  • route: Optional. The (Iron Router) route name this wizard will be bound to, the route needs a step parameter.
  • steps: Required. A list of steps for this wizard.
    • id: Required. Id of the step, also used for the route parameter.
    • title: Optional. The title displayed in the breadcrumbs.
    • template: Optional. Uses a default template with a quickform if not set.
    • schema: Optional. Only required if don't use a custom template.
    • formId: Optional. The AutoForm form id used in the template. Appends '-form' to the step.id if not set. Used to attach submit handlers and retrieve the step data.
    • data: Optional. Object with initial data for the step, for example a document, when using an update form. Overwrites previous saved data.
    • onSubmit: Optional. This function is executed after the form is submitted and validates. this references to the AutoForm instance. Shows the next step by default. Parameters:
      • data: The current step data.
      • wizard: The wizard instance.
  • buttonClasses: Optional. CSS classes to add to the buttons.
  • nextButton: Optional. Defaults to Next.
  • backButton: Optional. Defaults to Back. Set to false, to not render this button.
  • confirmButton: Optional. Defaults to Confirm.
  • persist: Optional. Persist the step data in localStorage. Defaults to true.
  • clearOnDestroy: Optional. Clear the cache storage after closing the wizard. Defaults to false.
  • stepsTemplate: Optional. A custom steps template.
  • stepTemplate: Optional. A custom default template for each step.

Custom attributes

Wizard configuration attributes can be extended with Wizard.extendOptions

  Wizard.extendOptions(['wizardClass']);

with default value:

  Wizard.extendOptions(['editButton', 'wizardClass'], {wizardClass: 'nav-wizard'});

onSubmit

Use this callback to process the form data.

onSubmit: function(data, wizard) {
  var self = this;
  Orders.insert(_.extend(wizard.mergedData(), data), function(err, id) {
    if (err) {
      self.done();
    } else {
      Router.go('viewOrder', {
        _id: id
      });
    }
  });
}

Arguments:

  • data: Form data of the current step.
  • wizard: The wizard instance.

this references to the AutoForm instance, see the AutoForm documentation for more information.

Wizard instance methods

The wizard instance is added to your step templates data context, so you can access these methods in your event handlers etc.

  • mergedData(): Get all data from previous steps. Does not include data of the current step in the onSubmit callback.
  • next([data]): Go to the next step. Optinionally pass data of the current step to make it available in mergedData().
  • previous(): Go to the previous step.
  • show(id): Show a specific step by id or index.
  • setData(id, data) Store data for the supplied step id, use this if you're using custom onSubmit handlers and use show() to skip steps based on the submitted data for example.
  • isFirstStep([id]): Omit the id argument to use the active step.
  • isLastStep([id]): Omit the id argument to use the active step.
  • indexOf(id): Get the index of the specified step id.

Example usage:

Template.wizardStep2.events({
  'click .back': function(e, template) {
    e.preventDefault();
    this.wizard.previous();
  }
});

Using routers

It's possible to bind the wizard to a router. Iron Router and Flow Router are supported by default. If you're using a different router, it's easy to setup custom bindings.

Configuring a router

  • note that Wizard is only available in client code.
  1. First add the route name you want to use to your wizard instance.
{{> wizard id="order-wizard" route="order" steps=steps}}

Iron Router

First add the Wizard Iron Router package.

meteor add forwarder:autoform-wizard-iron-router

Enable the router bindings.

Wizard.useRouter('iron:router');

Add a new route to your router config, with the :step parameter.

Router.route('/order/:step', {name: 'order'});

Flow Router

First add the Wizard Flow Router package.

meteor add forwarder:autoform-wizard-flow-router

Enable the router bindings.

Wizard.useRouter('kadira:flow-router');

Add a new route to your router config, with the :step parameter.

FlowRouter.route('/order/:step', {name: 'order'});

Custom router bindings

If you use a different router you can easily setup custom bindings. This example will you show how to bind the wizard to Flow Router (meteorhacks:flow-router).

Wizard.registerRouter('kadira:flow-router', {
  go: function(name, stepId) {
    FlowRouter.go(name, this.getParams(stepId));
  },
  getParams: function(stepId) {
    var route = Router.current()
      , params = route.params || {};

    return _.extend(params, {step: stepId});
  },
  getStep: function() {
    return FlowRouter.getParam('step');
  },
  path: function(name, stepId) {
    return FlowRouter.path(name, this.getParams(stepId));
  }
});

Then to enable Flow Router add the following line to your client code.

Wizard.useRouter('kadira:flow-router');

Todo

  • Improve documentation
  • Write some tests
  • Probably more, just let me know or submit a pull request :)

meteor-wizard's People

Contributors

pagebakers avatar samuelluis avatar zckly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

meteor-wizard's Issues

Expose WizardConstructor for add custom methods

If WizardConstructor object was expose is posible to add custom methods.

Maybe, Wizard.WizardConstructor

Right know I just using Wizard.extendOptions from proposed PR #38 for extend WizardConstructor but exposed object constructor is more appropiate.

Edit: Created new PR #38

i18n not working for buttons

Hi,

it seems that the button labels are not changed a function is passed as the button label.

nextButton:     function() { return i18n('enroll.next'); },
backButton:     function() { return i18n('enroll.back'); },
confirmButton:  function() { return i18n('enroll.confirm'); },

The button text gets set for the initial language, but the function does not rerun in the case of a change to the language.

The same thing works fine for the form title.

Validation error on custom form

The below code is in Jade/Livescript but is hopefully clear. I have a multi-step wizard. The first step requires you to select a resource, while the next two let you set a start/end date for when that resource is leased. The first screen works fine, and I can select a resource. The next screen refuses to let me set a date. Any input tells me that a start date is required when I click Next. It doesn't matter whether my date is valid or present. The error is always the same. Here are my step definitions for the first two steps, the first of which works fine:

Template.newLease.helpers do

steps: -> [
{
id: "select"
title: "Select"
schema: new SimpleSchema do
resourceId:
type: String
regEx: SimpleSchema.RegEx.Id
autoform:
options: ->
resources = Resources.find().fetch()
_.map resources, (r) -> {label: r.title, value: r._id}
}
{
id: "startDate"
title: "Start date"
template: "startDate"
formId: "startDateForm"
schema: new SimpleSchema do
start:
label: "Start time"
type: Date
}
...
]

And my templates:

template(name = "newLease")
h2 New lease
+wizard(id = "newLease" steps=steps)

template(name = "calendar")
#calendar

template(name = "startDate")
.row
.col-md-6
+autoForm(id = "startDateForm" doc=step.data schema=step.schema)
+afQuickField(name = "start" type = "datetime")
+wizardButtons
.col-md-6
+calendar

Any idea what I'm missing? Thanks for any help.

Doesn't work for more than two (2) steps

I used the demo example to get two steps working in my meteor app (using Semantic UI). However, as soon I add a third step, the "Next" button becomes greyed out.

Doesn't work with datepicker (aldeed:autoform-bs-datepicker)

I'm using aldeed:autoform-bs-datepicker and I've added a couple of datepickers to my wizard, but they fail to validate: "Start date must be a Date". I'm guessing that the wizard is reading the string shown in the text input rather than the date object.

ReferenceError: SimpleSchema is not defined

Added package and included following in app/lib/wizard.js:

Schema = {};

Schema.stepOne = new SimpleSchema({ ...

along with:

Items.attachSchema([
  Schema.stepOne,
  Schema.stepTwo,
  Schema.stepThree,
  Schema.stepFour,
  Schema.stepFive
]);

Getting following error:

Your app is crashing. Here's the latest log.


/Users/user/.meteor/packages/meteor-tool/.1.1.3.1wysac9++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:245
                        throw(ex);
                              ^
ReferenceError: SimpleSchema is not defined
  at app/lib/wizard.js:4:22
  at app/lib/wizard.js:95:3 ...

As an additional side note, because I am using FlowRouter I also tried to implement the code that binds Wizard to FlowRouter, but received a similar error that Wizard was not defined.

Example of using onSubmit hook?

The documentation mentions using the onSubmit hook, but does not give a specific example. How do we use the onSubmit hook?

E.g. in AutoForm, hooks are used as such:

AutoForm.hooks({
  "autoform-wizard": {
    onSubmit: function () {
      console.log("submit");
    }
  }
});

However, the above code does not work with an AutoForm Wizard by the same ID.

Can't get the Next / Back buttons to show

Hey,

First of all, thanks for a great package! Makes my life so much easier :) Quick question: how would you go about showing the Next / Back buttons? I went through all the documentation, I went through the source code of your example, and through the source code of the package itself, but I can't figure out how to do it.

Btw, your example shows only the Submit button as well -- there's no Back / Next button there either!

Thanks and please let me know if I there's anything I can do to help!

problem on Back button

here i am using back button in my wizard.
here is the code
Template.TemplateName.events({
'click .back': function(e, template) {
e.preventDefault();
this.wizard.previous();
}
});
it works fine.
but i want to move back to particular wizardStep
here the code i used :
Template.TemplateName.events({
'click .back': function(e, template) {
e.preventDefault();
this.wizard.previous("PreviousTemplateName");
}
});
It's not moving back to desired step and also some times stuck the entire wizard.
Please show me solution for my problem

Support select2 custom options

I'm using the autoform select2 package - https://atmospherejs.com/aldeed/autoform-select2
It would be nice to have a way to pass in custom options like so

Template.example.helpers({
s2Opts: function () {
return {placeholder: 'foo', tags: true};
}
});

which is added to the
{{> afFieldInput name="tags" type="select2" multiple=true select2Options=s2Opts}}

I guess you would need a way to set this per select2 field

wizard steps

I am using wizard in modal dialog when there are more number of steps we can't see all the steps in the wizard, for example if I have 10 steps I can traverse all those steps what ever I want but the problem is if modal size can show only 4 steps and in the 5th step I can access my code but can't see my step name in the wizard.how to slove this problem.
or
if i want to change wizard steps from top to left side where i should change...

How to initial data for update form?

I would like to initial data for update form.
I have 3 steps

// Template
{{> wizard id="productUpdate" steps=steps doc=data stepsTemplate="steps_bootstrap3" clearOnDestroy=true}}
------------
{{#autoForm id="generalStep" schema=step.schema doc=step.data}}......
{{#autoForm id="loanAmountStep" schema=step.schema doc=step.data}}......
{{#autoForm id="chargStep" schema=step.schema doc=step.data}}......

// Helper
Template.productUpdate.helpers({
    data: function () {
        var data = Collection.Product.findOne(this._id);
        return data;
    },
    steps: function () {
        return [
            {
                id: 'general',
                title: 'General',
                template: 'generalStep',
                formId: 'generalStep',
                schema: Schema.Product.general
            },
             ..............................

            {
                id: 'charge',
                title: 'Charge',
                template: 'chargStep',
                formId: 'chargStep',
                schema: Schema.Product.charge,
                onSubmit: function (data, wizard) {
                    var self = this;
                    var extend = _.extend(wizard.mergedData(), data);
                    // update doc
                }
            }
        ]
    }
});

Multi step form: clicking back then next from 2nd step loses 2nd step's data

I'm using a quick wizard with 3 steps. The 2nd and 3rd step use a custom template each defining an autoform.

When I'm on the 2nd step and I fill out the autoform then click next to the 3rd step and fill out the 3rd step's autoform, then:

  1. click back: I'm on the 2nd step and all entered data is present
  2. click next: I'm now on the 3rd step and all my entered data is cleared!
  3. click back: I'm now on the 2nd step and my entered data is present
  4. click back: I'm now on the 1st step and my entered data is present
  5. click next: I'm ow on the 2nd step and my entered data is cleared!

Why does moving forward through the wizard (by clicking next) seem to clear that next step if data was entered?

I've checked the this.data.wizard.mergedData() and it is also losing the data...

Is this the expected behaviour? Is there a bug? Or might I be doing something wrong?

Can't move past step 2

For someone reason I can't get past step two it just reloads back to step one, is there an example with four or five steps. Maybe this is something to do with the routes. Attached gif showing the issue

form_wizard_issue

Wizard navigation not working

Everything is working fine but the navigation / layout I'm using bootstrap 3 template so not sure why it's not getting picked up any ideas would be great

screen shot 2015-08-19 at 10 20 56 pm

Create a core meteor-wizard and put autoform-wizard in a separate package.

Hi @Pagebakers I read meteor-wizard code many times and I think is a wonderful writed code and must be reuse for more use cases than AutoForm wizardยดs.
Right know I need a tabbed interface and pick this package https://github.com/meteortemplates/tabs and start to look how can do the same with meteor-wizard. I believe that next steps is create a more general core package without AutoForm and even Blaze stuff and build AutoForm Wizard on a separate package over this core.

This project can be really interesting for the meteor community
What you think?

ReferenceError: Wizard is not defined

Getting the following error when adding "Wizard.useRouter('iron:router');"

  • ReferenceError: Wizard is not defined

Here is my route

Router.route('createPost', {
    layoutTemplate: 'layoutApp',
    path: '/create-post/:step',
    name: 'createPost',
    waitOn: function(){
        return [Meteor.subscribe('currentUser')];
    }
});

{{> wizard id="posts" steps=steps route="createPost" stepsTemplate="steps_semantic_ui" buttonClasses="ui button"}}

Wizards do not work with more than two steps

Issue #50 was closed without resolution. There may be a bug that prevents wizards with more than two steps. With the following code, the 'next' button on step two fails to activate:

Template.addApiBackendWizard.helpers({
  "steps": function () {
    var step1 = new SimpleSchema({
      "test1": {
        type: String
      }
    });

    var step2 = new SimpleSchema({
      "test2": {
        type: String
      }
    });

    var step3 = new SimpleSchema({
      "testing": {
        type: String
      }
    });

    var steps = [{
      id: 'step1',
      title: 'Step 1',
      schema: step1
    }, {
      id: 'step2',
      title: 'Step 2',
      schema: step2
    }, {
      id: 'step3',
      title: 'Step 3',
      schema: step3
    }];

    return steps;
  }
});

I have tried with the following template:

<template name="addApiBackendWizard">
  <h1>Add API Backend Wizard</h1>
  {{> wizard
    id="add-api-backend-wizard"
    steps=steps
    buttonClasses="btn btn-default"
    persist=false
  }}
</template>

Route seems to be hardcoded

I assumed we would be able to define the name for the route to use, but it seems to be hardcoded in wizard.html

   <li class="{{activeStepClass id}}"><a href="{{pathFor 'setup' step=id}}">{{title}}</a></li>

adding wizardClasses to the options

Today I wanted to style the wizard via semantic-ui grid. For the purpose I needed to pass the classes "ui grid" to the wizard, (not willing to copy the entire css and pass it to .wizard). I decided i will edit the package.

I added 'wizardClasses' to the _the options in wizard.js
and edited the line in the html file like so:

<div id="{{wizard.id}}" class="wizard {{wizardClasses}}"> 

wizard class gets passed to the wizard, and any other static classes but its not passing any dynamic if i call it like so

 {{> wizard id="basic-wizard" steps=steps wizardClasses="grid ui"}}

What am I missing?

Can I use the same template for different forms?

Hello,
I am creating a quiz that only contains question + answer forms. Basically all forms could be in the same template, but defined differently in schemas. I don't want to define the same template with different ids. I have made this setup, but after submitting the first form the next button gets disabled. As I figured out, it is a double submit prevention. It is triggered after pressing the submit button, but it is not changed back to normal before loading next question. Is there a quick solution to this problem? I would like to know your opinion on this one.
There is my example.
The form template name is the same for all forms, but form ids and schemas are different:

<template name="test">
{{console.log this}}
{{#autoForm schema=this.step.schema id=this.step.formId}}
<div class="headline">
    <h2>{{this.step.title}}</h2>
</div>
<fieldset>
    {{> afQuickField name='answers'}}
</fieldset>
<button type="submit" class="btn btn-success btn-lg pull-right">Next</button>
{{/autoForm}}

The steps definition:

 return [
        {
            id: 'question1',
            formId: 'question1',
            title: 'test1',
            template: 'test',
            schema: Schema.pointsUser.question1
        },
        {
            id: 'question2',
            formId: 'question2',
            template: 'test',
            title: 'test2',
            schema: Schema.pointsUser.question2
        },
        {
            id: 'question3',
            formId: 'question3',
            template: 'test',
            title: 'test3',
            schema: Schema.pointsUser.question3
        }
];

And the schemas:

question1: new SimpleSchema({
    answers: {
        type: [String],
        autoform: {
            type: "select-checkbox",
            label: false,
            options: function () {
                return [
                    {
                        label: "qwerty",
                        value: 1
                    },
                    {
                        label: "asdfg",
                        value: 2
                    },
                    {
                        label: "zxczxv",
                        value: 3
                    }
                ];
            }
        }
    }
}),
question2: new SimpleSchema({
    answers: {
        type: String,
        autoform: {
            type: "select-radio",
            label: false,
            options: function () {
                return [
                    {
                        label: "qwerty",
                        value: 1
                    },
                    {
                        label: "zxcvbfr",
                        value: 2
                    },
                    {
                        label: "aaaa",
                        value: 3
                    }
                ];
            }
        }
    }
}),
question3: new SimpleSchema({
    answers: {
        type: String,
        autoform: {
            type: "select-radio",
            label: false,
            options: function () {
                return [
                    {
                        label: "123",
                        value: 1
                    },
                    {
                        label: "312",
                        value: 2
                    },
                    {
                        label: "753",
                        value: 3
                    }
                ];
            }
        }
    }
}),

Custom buttons not rendering

So I am trying to get some custom buttons added to a form I created using the example you provided, I did the following:

<template name="basic">
  {{#autoForm id="basic" route="basic" doc=step.data schema="Schemas.contactInformation" type="insert" collection="Orders"}}
    {{#each afFieldNames}}
          {{> afQuickField name=this.name options=afOptionsFromSchema}}
       {{/each}}
    {{> wizardButtons2}}
  {{/autoForm}}
</template>

and for the buttons template I have:

<template name="wizardButtons2">
  {{#with wizard}}
  <nav class="wizard-nav">
    {{#if showBackButton}}
    <button type="button" class="wizard-back-button {{buttonClasses}}">{{backButton}}</button>
    {{/if}}
    {{#if isLastStep}}
    <button type="submit" class="wizard-submit-button {{buttonClasses}}">{{confirmButton}}</button>
    {{else}}
    <button type="submit" class="wizard-next-button {{buttonClasses}}">{{nextButton}}</button>
    {{/if}}
  </nav>
  {{/with}}
</template>

No buttons show up however.

Do I need to create a helper for the wizardButtons2 template? It looks like the {{#with wizard}}} block is the issue. Anything I put in there doesn't render.

Thanks.

generation of json problem after submiting the wizard

I am using wizard in modal dialog
here is my schema
Schema{}
Schema.admin = new SimpleSchema({
'firstName': {
type: String,
index: 1,
label:'First Name'
},
'middleName': {
type: String,
index: 1,
label:'Middle Name'
}
});

Template.maintemp.helpers({
steps: function() {
return [{
id: 'dc_address',
title: 'Name',
template: 'admins',
formId: 'dc_adminInfo_form',
onSubmit: function(data, wizard) {
var params=_.extend(wizard.mergedData(), data);
console.log(params);
}
}]
})
here is my template

{{#autoForm id="dc_adminInfo_form" doc=this.data schema=Schema.admin}}
{{> afQuickField name="firstName" placeholder="First Name"}}
{{> afQuickField name="middleName" placeholder="Middle Name"}}

it is work fine when i am submit wizard first time and it display json schema in my console.
here is the problem is when i submit the wizard for second time without refreshing the webpage it displays the same json 2 times in my console,for the third time it display 3 times so on but when i refresh the page it dispaly correctly for one time.Help me by saying where I am going wrong

select2 selection erased after moving to the next step

I'm using the autoform select2 package - https://atmospherejs.com/aldeed/autoform-select2

Which is working fine however when you navigate to the next step whatever you selected is erased or not saved and you can't submit the form. Further more on the final step when you confirm due to this issue you get no error warning

My code

Posts = new Mongo.Collection("posts");

Schemas = {};
Schemas.postStep1 = new SimpleSchema({
    title: {
        type: String,
        label: mf('title', 'Title'),
        max: 200
    },
    type: {
        type: String,
        label: mf('type', 'Type'),
        max: 200,
        autoform: {
            type: "select2",
            options: function () {
                return [
                    {label: mf('testing', 'Testing'), value: 2013},
                    {label: "2014", value: 2014},
                    {label: "2015", value: 2015}
                ];
            }
        }
    },
    subType: {
        type: String,
        label: mf('subTile', 'Sub Title'),
        max: 200,
        autoform: {
            type: "select2",
            options: function () {
                return [
                    {label: "2013", value: 2013},
                    {label: "2014", value: 2014},
                    {label: "2015", value: 2015}
                ];
            }
        }
    },
    postDesc: {
        type: String,
        label: mf('postDescription', 'Post Description'),
        max: 2000
    }
});

Schemas.postStep2 = new SimpleSchema({
    unitsTotal: {
        type: Number,
        decimal: true,
        label: mf('quantity', 'Quantity')
    },
    unitOfMeasure: {
        type: String,
        label: mf('unitOfMeasure', 'Unit Of Measure'),
        max: 50,
        autoform: {
            type: "select2",
            options: function () {
                return [
                    {label: "2013", value: 2013},
                    {label: "2014", value: 2014},
                    {label: "2015", value: 2015}
                ];
            }
        }
    },
    use: {
        type: String,
        label: mf('use', 'Use'),
        max: 200
    },
    bestUsedBy: {
        type: Date,
        label: mf('bestUsedBy', 'Best Used By')//,
        /*
        autoform: {
            type: "bootstrap-datetimepicker"
        }*/
    }/*,
    mustUseBy: {
        type: Date,
        label: "Must Use By",
        autoform: {
            type: "bootstrap-datetimepicker"
        }
    }*/,
    idealUse: {
        type: String,
        label: mf('idealUse', 'Ideal Use'),
        max: 200
    }
});

Schemas.postStep3 = new SimpleSchema({
    purpose: {
        type: String,
        label: mf('purpose', 'Purpose'),
        max: 200
    },
    salePrice: {
        type: Number,
        label: mf('salePriceUsd', 'Sale Price (USD)')
    },
    priceType: {
        type: String,
        label: mf('priceType', 'priceType')
    }
});

Schemas.postStep4 = new SimpleSchema({
    origin: {
        type: [Number],
        decimal: true,
        label: mf('origin', 'Origin'),
        max: 500,
        autoform: {
            type: "map",
            afFieldInput:{
                geolocation: true,
                searchBox: true,
                autolocate: true,
                height:'300px'
            }
        }
    },
    delivery: {
        type: String,
        label: mf('delivery', 'Delivery'),
        autoform: {
            type: "select2",
            options: function () {
                return [
                    {label: "2013", value: 2013},
                    {label: "2014", value: 2014},
                    {label: "2015", value: 2015}
                ];
            }
        }
    },
    handling: {
        type: String,
        label: mf('handling', 'Handling'),
        max: 1000,
        autoform: {
            type: "select2",
            options: function () {
                return [
                    {label: "2013", value: 2013},
                    {label: "2014", value: 2014},
                    {label: "2015", value: 2015}
                ];
            }
        }
    },
    audience: {
        type: String,
        label: mf('audience', 'Audience'),
        autoform: {
            type: "select2",
            options: function () {
                return [
                    {label: "2013", value: 2013},
                    {label: "2014", value: 2014},
                    {label: "2015", value: 2015}
                ];
            }
        }
    },
    posterId: {
        type: String,
        autoform: {
            type: "hidden",
            label: false
        },
        defaultValue:function(){ return this.userId }

    },
    posterName: {
        type: String,
        autoform: {
            type: "hidden",
            label: false
        },
        defaultValue:function(){
            var user = Meteor.users.findOne(this.userId);
            console.log(user);
            return this.userId
        }
    },
    isActive: {
        type: String,
        autoform: {
            afFieldInput: {
                type: "hidden"
            },
            afFormGroup: {
                label: false
            }
        },
        defaultValue:function(){ return true}
    },
    isClaimed: {
        type: String,
        autoform: {
            afFieldInput: {
                type: "hidden"
            },
            afFormGroup: {
                label: false
            }
        },
        defaultValue:function(){ return false}
    }
});

Posts.attachSchema([
    Schemas.postStep1,
    Schemas.postStep2,
    Schemas.postStep3,
    Schemas.postStep4
]);
Template.createPost.helpers({
    steps: function() {
        return [
            {
                id: 'postStep1',
                title: 'Step 1',
                formId: 'postStep1',
                schema: Schemas.postStep1
            },
            {
                id: 'postStep2',
                title: 'Step 2',
                formId: 'postStep2',
                schema: Schemas.postStep2
            },
            {
                id: 'postStep3',
                title: 'Step 3',
                formId: 'postStep3',
                schema: Schemas.postStep3
            },
            {
                id: 'postStep4',
                title: 'Step 4',
                formId: 'postStep4',
                schema: Schemas.postStep4,
                onSubmit: function(data, wizard) {
                    console.log(data);
                    // submit logic
                }
            }]
    }
});

Reactive multi page form

Trying to create a form that is multi pages and changes based on a few inputs. I am having issues populating the templates based on inputs. For example: form has a dropdown for "Number of campers?" It stores that value in collection after hitting next. On the 2nd page it displays [x number] of forms. Using the data on the 2nd to ask something on the 3rd and 4th page.

Currently every 'step' is being saved as a session. I was able to get the number value from this session. The only way I can get it to kind of work is to hardcode indexes into '''{{> afQuickField name="campers.0.firstName"}}'''

This package works perfect, but I can't seem to find a way to get the forms to respond properly on multi page form.

Buttons Label are not changing

I'm trying to change the button label ( default values ) but it not accepting the change.

Template.basic.helpers({
steps: function() {
return [{
id: 'contact-information',
title: 'Contact information',
schema: Schemas.contactInformation
}, {
id: 'payment-information',
title: 'Payment & confirm',
schema: Schemas.paymentInformation,
onSubmit: function(data, wizard) {
var self = this;
Orders.insert(_.extend(wizard.mergedData(), data), function(err, id) {
if (err) {
self.done();
} else {
Router.go('viewOrder', {
_id: id
});
}
});
}
}];
},
backButton: '< Previous'
});

"next" button simply reloads page

Firstly, I'm using an older version of meteor-wizard due to version constraints, so rather than wizardButtons, I'm using the template __wizard_nav.
Secondly,, I'm trying to use custom templates in a way that does not force me to manually insert the document. In other words, I'm actively trying to avoid using the onSubmit hook and prefer to rely on autoforms own methods.

template(name="offeringDetails")
  +autoForm(id="offering-details" doc=step.data schema=step.schema)
    +afQuickField(name='title')
    +afQuickField(name='summary')
    +afQuickField(name='description')
    +afQuickField(name="picture")
    +afQuickField(name='video')
    +afQuickField(name='corporateEntity')
    +afQuickField(name='prospectus')

    +__wizard_nav


template(name="offeringContract")
  +autoForm(id="offering-contract" doc=step.data schema=step.schema)
    +afQuickField(name='totalValuation')
    +afQuickField(name='threshold')
    +afQuickField(name='returnCap')
    +afQuickField(name='percentRevenueShared')
    +afQuickField(name='sharePrice')
    +afQuickField(name='sharesIssued')
    +afQuickField(name='sharesOffered')

    +__wizard_nav

    button.btn.btn-primary(type="submit") Create offering


template(name='newOffering')
  .container
    h2 Create an Offering
    +wizard(id="basic-wizard" steps=steps)
Template.newOffering.helpers
  steps: ->
    [
      {
       id: 'offering-details'
       title: 'Details'
       template: 'offeringDetails'
       schema: Schemas.OfferingDetails
      },
      {
       id: 'offering-contract'
       title: 'Contract'
       template: 'offeringContract'
       schema: Schemas.OfferingContract
      }
    ]
@Schemas.OfferingDetails = new SimpleSchema
 title:
   type: String
   max: 60
 description:
   type: String
   autoform:
     type: 'markdown'
 corporateEntity:
   type: String
   optional: true
   max: 144
 summary:
   type: String
   max: 144
 video:
   type: String
   optional: true
   autoform:
    placeholder: 'https://www.youtube.com/embed/NUN_bmiVmXo'
 picture:
   type: String
   optional: true
   autoform:
     afFieldInput:
       type: 'fileUpload'
       collection: 'offering_images'
   label: 'Offering Image'
 prospectus:
   type: String
   optional: true
   autoform:
     afFieldInput:
       type: 'fileUpload'
       collection: 'prospectuses'
   label: 'Prospectus'

@Schemas.OfferingContract = new SimpleSchema
  totalValuation:
    type: Number
    label: "How much money would you like to raise?"
    defaultValue: 100000
    min: 100
    autoform:
      type: 'usdCents'
  threshold:
    type: Number
    label: "Is there a minimum amount that is required to fulfill the Contract?"
    defaultValue: 0
    min: 0
    autoform:
      type: 'usdCents'
  returnCap:
    type: Number
    label: "Revenue sharing return cap. Past which, shareholders are no longer entitled to receive revenue share"
    defaultValue: 2
    min: 1
  percentRevenueShared:
    type: Number
    label: "The percent of gross revenue will be applied each period to pay back investors"
    defaultValue: 50
    min: 1
  sharePrice:
    type: Number
    label: "Minimum investment required per person (share price)"
    defaultValue: 1000
    min: 100
    autoform:
      type: 'usdCents'
  sharesIssued:
    type: Number
    label: "Total number of shares that will be created"
    min: 1
    autoValue: ->
      if @isInsert
        parseInt(parseInt(@siblingField('totalValuation').value) / parseInt(@siblingField('sharePrice').value))
        #automatic field user shouldn't enter directly
  sharesOffered:
    type: Number
    label: "Number of shares to be made available for investor purchase"
    min: 1
    autoValue: ->
      if @isInsert
        sharesToIssue = parseInt(parseInt(@siblingField('totalValuation').value) / parseInt(@siblingField('sharePrice').value))
        parseInt(sharesToIssue * parseInt(@siblingField('percentRevenueShared').value) / 100)
        #automatic field user shouldn't enter directly

@Schemas.Offering = new SimpleSchema
  contract:
    type: @Schemas.OfferingContract
  details:
    type: @Schemas.OfferingDetails

Support question dependencies between steps

I had a big schema which I split the sections into sub schemas to use in steps.
The following question dependency code works when all the questions were in one big schema:

// step 1 schema
companySchema = new SimpleSchema({
    selectCompany: {
        label: "Select company",
        type: String,
        optional: true,
        autoform: {
            type: "select2",
            options: function() {
                return _.map(CompanyCollection.find({}).fetch(), function(service) {
                    return {
                       label: service.companyName,
                       value: service._id
                    };
                });
            }
        }
    }
})

//step 2 schema - display ***chosenCompany*** based on ***selectCompany*** answer
companyDetailsSchema = new SimpleSchema({
    chosenCompany: {
        label: "Chosen company",
        type: String,
        optional: true,
        autoform: {
            afFieldInput: {
                type: function() {
                    if (AutoForm.getFieldValue("selectCompany") === undefined) {
                        return "hidden";
                    } else {
                        return "text";
                    };
                },
                value: function() {
                    if (AutoForm.getFieldValue("selectCompany") === "company") {
                        return AutoForm.getFieldValue("selectCompany"); // value of 'selectCompany'
                    } else {
                        return "";
                    };
                }
            },
            label: function() {
                if (AutoForm.getFieldValue("selectCompany") === undefined) {
                    return false;
                };
            }
        }
    }
})

Question: Is it possible to show/hide questions in step 2 based on answers in step 1?

Question: Howto add "Login" step. Skip step forward/backward if already logged in?

Hi :-)

How can I skip a step if it's not appropriate. I have this form progression:

PromiseStuff -> Login -> Verification -> Confirmation -> DeliverStuff

I want to skip Login and/or Verification steps if the user is logged in and/or verified.

PromiseStuff.next() -> Confirmation
Confirmation.prev() -> PromiseStuff

I didn't see a way to do this, but maybe I missed something?

Optimally, it would be nice to pass a configuration option skipIf a boolean function to tell the form logic to keep going forward/backwards.

Any suggestions?

Thanks!

More than 2 steps issue

Can someone please upload a simple example with more than 2 steps?

I've downloaded the example, simply added a third step between the two that are already defined, but I can't get past the second step.
After I fill in the data from the first step and hit 'Next', the 'Next' button on the second step is active for half a second or so, and then becomes disabled.
Moreover, after I hit 'Back' to get back to step one, the 'Next' button on the first step becomes disabled as well.

This is the relevant code where I think I'm doing something wrong.

Template.basic.helpers({
  steps: function() {
    return [{
      id: 'contact-information',
      title: 'Contact information',
      schema: Schemas.contactInformation
    }, {
      id: 'foo',
      title: 'foo',
      schema: Schemas.foo
    }, {
      id: 'payment-information',
      title: 'Payment & confirm',
      schema: Schemas.paymentInformation,
      onSubmit: function(data, wizard) {
        var self = this;
        Orders.insert(_.extend(wizard.mergedData(), data), function(err, id) {
          if (err) {
            self.done();
          } else {
            Router.go('viewOrder', {
              _id: id
            });
            console.log(wizard.mergedData());
            wizard.clearData();
          }
        });
      }
    }];
  }
});

Exception in template helper: ReferenceError: Schemas is not defined

I'm getting the following error not sure why my code is exactly like your example

This is the error
Exception in template helper: ReferenceError: Schemas is not defined

Here is my code

Template

<template name="createPost">
    <div id="main-wrapper">
        <div class="row">
            {{> wizard id="create-post"  steps=steps}}
        </div>
    </div>
</template>

TemplateJS / Helper

Template.createPost.helpers({
    steps: function() {
        return [{
            id: 'contact-information',
            title: 'Contact information',
            schema: Schemas.postsInformation
        }];
    }
});

Collection / posts.js (shared folder)

Posts = new Mongo.Collection("posts");

var Schemas = {};

Schemas.postsInformation = new SimpleSchema({
    title: {
        type: String,
        label: "Title",
        max: 200
    },
    type: {
        type: String,
        label: "Type",
        max: 200
    },
    subType: {
        type: String,
        label: "Sub Type",
        max: 200
    },
    posterId: {
        type: String,
        label: "Poster"
    },
    posterName: {
        type: String,
        label: "Poster Name"
    },
    postDesc: {
        type: String,
        label: "Post Desc",
        max: 2000
    }
});

Schemas.postsUse = new SimpleSchema({
    title: {
        type: String,
        label: "Title",
        max: 200
    },
    type: {
        type: String,
        label: "Type",
        max: 200
    },
    subType: {
        type: String,
        label: "Sub Type",
        max: 200
    },
    posterId: {
        type: String,
        label: "Poster"
    },
    posterName: {
        type: String,
        label: "Poster Name"
    },
    postDesc: {
        type: String,
        label: "Post Desc",
        max: 2000
    }
});

Posts.attachSchema([
    Schemas.postsInformation,
    Schemas.postsUse
]);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.