Meteor-Community-Packages / meteor-autoform

AutoForm is a Meteor package that adds UI components and helpers to easily create basic forms with automatic insert and update events, and automatic reactive validation.
MIT License
1.44k stars 328 forks source link

Question: Insert/Update with a Drop down control #422

Closed aadamsx closed 9 years ago

aadamsx commented 9 years ago

How do you go about updating/inserting based on a drop down control?

At the moment I have the drop down control rendering on the page and sourcing its data from a countries collection.

The code is as follows:

client\view.js

... sniped ...
            {{#autoForm collection="Address" id="koneUscStepOne" type="insert" class="form-horizontal"}}
... sniped ...
                {{> afQuickField name="physicalInCareOfName" template="bootstrap3-horizontal" label-class="col-lg-2" input-col-class="col-lg-10" placeholder="Do not put your name here."}}
                {{> afQuickField name="street1" template="bootstrap3-horizontal" label-class="col-lg-2" input-col-class="col-lg-10" placeholder="123 Main Street"}}
                {{> afQuickField name="apartment1" template="bootstrap3-horizontal" label-class="col-lg-2" input-col-class="col-lg-10" placeholder="43 or 532-B. Do not add Apt or #."}}
                {{> afQuickField name="city1" template="bootstrap3-horizontal" label-class="col-lg-2" input-col-class="col-lg-10" placeholder="Deer Park or Houston."}}
                <div class="form-group">
                    <label class="col-lg-2 control-label">Country</label>
                    <div class="col-lg-10">
                        <select class="form-control">
                            <option value="">- Select</option>
                            {{#each countries}}
                                <option value="{{value}}">{{name}}</option>
                            {{/each}}
                        </select>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-lg-10 col-lg-offset-2">
                        <!--<button class="btn btn-default">Cancel</button>-->
                        <button type="submit" class="btn ">Skip & Continue</button>
                        <button type="submit" class="btn btn-primary">Save & Continue</button>
                    </div>
                </div>
            {{/autoForm}}
... sniped ...

common\schemas.js

Schemas.Address = new SimpleSchema({
    physicalInCareOfName: {
        type: String,
        optional: true,
        label: "In Care Of Name",
        max: 32
    },
    street1: {
        type: String,
        optional: true,
        label: "Number and street",
        max: 32
    },
    apartment1: {
        type: String,
        optional: true,
        label: "Apartment number",
        max: 11
    },
    city1: {
        type: String,
        optional: true,
        label: "Town or City",
        max: 32
    },
    country: {
        type: String,
        optional: true
    }
});

common\collections.js

Address = Collections.Address = new Mongo.Collection("Address");
Address.attachSchema(Schemas.Address);

Countries =  new Mongo.Collection("Countries");

common\routes.js

Router.route('/k1cr1-step-two', {
    name: 'kone.steptwo.view',
    controller: 'koneUscStepTwoController'
});
koneUscStepTwoController = RouteController.extend({
    template: 'koneUscStepTwo',
    waitOn: function () {
        Meteor.subscribe("Countries");
    }
});
koneUscStepTwoController.helpers({
    countries: function () {
        var countries = Countries.find();
        console.log(countries);
        return countries;
    }
});

server\publish.js

Meteor.publish("Countries", function () {
    var countries = Countries.find({});
    console.log(countries);
    return countries;
});

I don't see a way to nexus the drop down with the schema for the update/insert (basically to tell Autoform that the drop down value should be included in the update/insert).

I've seen in your documentation here you have, for example, address.state in your template, and set the allowedValues option.

I've been reading a little about your autoform.options. It sounds like I could possibly do what I want to do with this method? I'll need to not use the simple-schema, but a "full schema". Is this the right track? Will you provide an example of this?

I want to get my values from a Collection. Is there a way through your template to source values from, say State Collection, but update the Address Collection with the chosen value?

aadamsx commented 9 years ago

I tried to add autoform.options, but the terminal shows some strange output, and it's not working (where is the _.map coming from?). Does autoform.options work inside of SimpleSchema?

added countries to the schema like so:

Schemas.Address = new SimpleSchema({
... sniped ...
    countries: {
        type: Array,
        label: "test",
        optional: true
    },
    'countries.$': {
        type: String,
        autoform: {
            options: function () {
                return _.map(Countries.find().fetch(), function (object, idx) {
                    return {label: object.name, value: object._id};
                });
            }
        }
    },
... sniped ...

and added this line to the template:

{{> afArrayField name="countries" options=countries}}

Everything else is the same as above...

Also, just in case you're interested, here's the output from the meteor session terminal after I updated the files and saved:

=> Client modified -- refreshing
I20141030-23:37:10.879(-5)? { _mongo:
I20141030-23:37:10.879(-5)?    { _connectCallbacks: [ [Function] ],
I20141030-23:37:10.880(-5)?      _observeMultiplexers:
I20141030-23:37:10.882(-5)?       { '{"ordered":false,"collectionName":"users","selector":{"_id":"8Eh6xad2HuxH3N7F8","services.resume.loginTokens.hashedToken":"UR16jUInwgtzhmVtR1KUU5yt+x1EHCqhkItBZK85CZY="},"options":{"transform":null,"fields":{"_id":1}}}': [Object],
I20141030-23:37:10.882(-5)?         '{"ordered":false,"collectionName":"meteor_accounts_loginServiceConfiguration","selector":{},"options":{"transform":null,"fields":{"secret":0}}}': [Object],
I20141030-23:37:10.882(-5)?         '{"ordered":false,"collectionName":"users","selector":{"_id":"8Eh6xad2HuxH3N7F8"},"options":{"transform":null,"fields":{"profile":1,"username":1,"emails":1}}}': [Object] },
I20141030-23:37:10.882(-5)?      _onFailoverHook: { nextCallbackId: 14, callbacks: [Object] },
I20141030-23:37:10.883(-5)?      _docFetcher: { _mongoConnection: [Circular], _callbacksForCacheKey: {} },
I20141030-23:37:10.884(-5)?      _oplogHandle:
I20141030-23:37:10.884(-5)?       { _oplogUrl: 'mongodb://127.0.0.1:3001/local',
I20141030-23:37:10.884(-5)?         _dbName: 'meteor',
I20141030-23:37:10.885(-5)?         _oplogLastEntryConnection: [Object],
I20141030-23:37:10.886(-5)?         _oplogTailConnection: [Object],
I20141030-23:37:10.887(-5)?         _stopped: false,
I20141030-23:37:10.888(-5)?         _tailHandle: [Object],
I20141030-23:37:10.901(-5)?         _readyFuture: [Object],
I20141030-23:37:10.902(-5)?         _crossbar: [Object],
I20141030-23:37:10.903(-5)?         _lastProcessedTS: [Object],
I20141030-23:37:10.903(-5)?         _baseOplogSelector: [Object],
I20141030-23:37:10.903(-5)?         _catchingUpFutures: [] },
I20141030-23:37:10.903(-5)?      db:
I20141030-23:37:10.903(-5)?       { domain: null,
I20141030-23:37:10.904(-5)?         _events: {},
I20141030-23:37:10.904(-5)?         _maxListeners: 10,
I20141030-23:37:10.904(-5)?         databaseName: 'meteor',
I20141030-23:37:10.905(-5)?         serverConfig: [Object],
I20141030-23:37:10.905(-5)?         options: [Object],
I20141030-23:37:10.905(-5)?         _applicationClosed: false,
I20141030-23:37:10.973(-5)?         slaveOk: false,
I20141030-23:37:10.973(-5)?         bufferMaxEntries: -1,
I20141030-23:37:10.973(-5)?         native_parser: false,
I20141030-23:37:10.974(-5)?         bsonLib: [Object],
I20141030-23:37:10.974(-5)?         bson: [Object],
I20141030-23:37:10.974(-5)?         bson_deserializer: [Object],
I20141030-23:37:10.974(-5)?         bson_serializer: [Object],
I20141030-23:37:10.974(-5)?         _state: 'connected',
I20141030-23:37:10.974(-5)?         pkFactory: [Object],
I20141030-23:37:10.975(-5)?         forceServerObjectId: false,
I20141030-23:37:10.975(-5)?         safe: false,
I20141030-23:37:10.975(-5)?         notReplied: {},
I20141030-23:37:10.975(-5)?         isInitializing: true,
I20141030-23:37:10.975(-5)?         openCalled: true,
I20141030-23:37:10.975(-5)?         commands: [],
I20141030-23:37:10.975(-5)?         logger: [Object],
I20141030-23:37:10.976(-5)?         tag: 1414730034581,
I20141030-23:37:10.976(-5)?         eventHandlers: [Object],
I20141030-23:37:10.976(-5)?         serializeFunctions: false,
I20141030-23:37:10.976(-5)?         raw: false,
I20141030-23:37:10.977(-5)?         recordQueryStats: false,
I20141030-23:37:10.977(-5)?         retryMiliSeconds: 1000,
I20141030-23:37:10.977(-5)?         numberOfRetries: 60,
I20141030-23:37:10.977(-5)?         readPreference: [Object] },
I20141030-23:37:10.977(-5)?      _primary: '127.0.0.1:3001' },
I20141030-23:37:10.977(-5)?   _cursorDescription:
I20141030-23:37:10.978(-5)?    { collectionName: 'Countries',
I20141030-23:37:10.978(-5)?      selector: {},
I20141030-23:37:10.978(-5)?      options: { transform: null } },
I20141030-23:37:10.978(-5)?   _synchronousCursor: null }
I20141030-23:37:20.910(-5)? { _mongo:
I20141030-23:37:20.910(-5)?    { _connectCallbacks: [ [Function] ],
I20141030-23:37:20.911(-5)?      _observeMultiplexers:
I20141030-23:37:20.911(-5)?       { '{"ordered":false,"collectionName":"users","selector":{"_id":"8Eh6xad2HuxH3N7F8","services.resume.loginTokens.hashedToken":"UR16jUInwgtzhmVtR1KUU5yt+x1EHCqhkItBZK85CZY="},"options":{"transform":null,"fields":{"_id":1}}}': [Object],
I20141030-23:37:20.911(-5)?         '{"ordered":false,"collectionName":"meteor_accounts_loginServiceConfiguration","selector":{},"options":{"transform":null,"fields":{"secret":0}}}': [Object],
I20141030-23:37:20.911(-5)?         '{"ordered":false,"collectionName":"users","selector":{"_id":"8Eh6xad2HuxH3N7F8"},"options":{"transform":null,"fields":{"profile":1,"username":1,"emails":1}}}': [Object] },
I20141030-23:37:20.911(-5)?      _onFailoverHook: { nextCallbackId: 19, callbacks: [Object] },
I20141030-23:37:20.911(-5)?      _docFetcher: { _mongoConnection: [Circular], _callbacksForCacheKey: {} },
I20141030-23:37:20.912(-5)?      _oplogHandle:
I20141030-23:37:20.912(-5)?       { _oplogUrl: 'mongodb://127.0.0.1:3001/local',
I20141030-23:37:20.912(-5)?         _dbName: 'meteor',
I20141030-23:37:20.912(-5)?         _oplogLastEntryConnection: [Object],
I20141030-23:37:20.912(-5)?         _oplogTailConnection: [Object],
I20141030-23:37:20.912(-5)?         _stopped: false,
I20141030-23:37:20.912(-5)?         _tailHandle: [Object],
I20141030-23:37:20.913(-5)?         _readyFuture: [Object],
I20141030-23:37:20.913(-5)?         _crossbar: [Object],
I20141030-23:37:20.913(-5)?         _lastProcessedTS: [Object],
I20141030-23:37:20.913(-5)?         _baseOplogSelector: [Object],
I20141030-23:37:20.913(-5)?         _catchingUpFutures: [] },
I20141030-23:37:20.913(-5)?      db:
I20141030-23:37:20.913(-5)?       { domain: null,
I20141030-23:37:20.914(-5)?         _events: {},
I20141030-23:37:20.914(-5)?         _maxListeners: 10,
I20141030-23:37:20.914(-5)?         databaseName: 'meteor',
I20141030-23:37:20.914(-5)?         serverConfig: [Object],
I20141030-23:37:20.914(-5)?         options: [Object],
I20141030-23:37:20.914(-5)?         _applicationClosed: false,
I20141030-23:37:20.915(-5)?         slaveOk: false,
I20141030-23:37:20.915(-5)?         bufferMaxEntries: -1,
I20141030-23:37:20.915(-5)?         native_parser: false,
I20141030-23:37:20.915(-5)?         bsonLib: [Object],
I20141030-23:37:20.916(-5)?         bson: [Object],
I20141030-23:37:20.916(-5)?         bson_deserializer: [Object],
I20141030-23:37:20.916(-5)?         bson_serializer: [Object],
I20141030-23:37:20.916(-5)?         _state: 'connected',
I20141030-23:37:20.916(-5)?         pkFactory: [Object],
I20141030-23:37:20.916(-5)?         forceServerObjectId: false,
I20141030-23:37:20.917(-5)?         safe: false,
I20141030-23:37:20.917(-5)?         notReplied: {},
I20141030-23:37:20.917(-5)?         isInitializing: true,
I20141030-23:37:20.917(-5)?         openCalled: true,
I20141030-23:37:20.917(-5)?         commands: [],
I20141030-23:37:20.918(-5)?         logger: [Object],
I20141030-23:37:20.918(-5)?         tag: 1414730034581,
I20141030-23:37:20.918(-5)?         eventHandlers: [Object],
I20141030-23:37:20.918(-5)?         serializeFunctions: false,
I20141030-23:37:20.918(-5)?         raw: false,
I20141030-23:37:20.918(-5)?         recordQueryStats: false,
I20141030-23:37:20.918(-5)?         retryMiliSeconds: 1000,
I20141030-23:37:20.919(-5)?         numberOfRetries: 60,
I20141030-23:37:20.919(-5)?         readPreference: [Object] },
I20141030-23:37:20.919(-5)?      _primary: '127.0.0.1:3001' },
I20141030-23:37:20.919(-5)?   _cursorDescription:
I20141030-23:37:20.919(-5)?    { collectionName: 'Countries',
I20141030-23:37:20.919(-5)?      selector: {},
I20141030-23:37:20.920(-5)?      options: { transform: null } },
I20141030-23:37:20.920(-5)?   _synchronousCursor: null }
aadamsx commented 9 years ago

I got it to work:

{{> afQuickField name="countries" }}
    countries: {
        type: String,
        autoform: {
            options: function () {
                return _.map(Countries.find().fetch(), function (object, idx) {
                    return {label: object.name, value: object.value};
                });
            }
        }
    },

By the way, the only reason I got this to work carefully reading your documentation (readme). I found an example down at the bottom under the heading Calculate options in the schema and that made all the difference.

I have to say, your documentation makes working with your repository (despite all the many variations and options) manageable or event great.

Thank you for your excellent documentation and your new demo repository (please keep adding to that)!

aldeed commented 9 years ago

Thanks, @aadamsx. FYI, you should be able to use Countries.find().map() directly instead of _.map. Might be more efficient, but I've never actually compared.

aadamsx commented 9 years ago

Oh, thanks. You mean like this?

return Countries.find().map(function (obj) {
                    return {label: obj.name, value: obj.value};
                    });
aldeed commented 9 years ago

Yes

tried2call commented 8 years ago

Hello ! I understand that the 'label' populates the dropdown, and the 'value' is what is stored on a 'submit' event. These work fine for me, but ... My question: When I select an entry from the dropdown, how do I reference that item's 'value' ? In other words, what is that selected 'value' called ?
I've tried collection._id, tried saving 'this._id' to a variable for later use, tried the actual code used to reference the 'value' (in my case, c._id ) to no avail.

I'm trying to use the selected 'value' of dropdown #1 to link to a second dropdown #2 and down-select the items presented in dropdown #2.

I feel like I'm missing something that should be obvious ! Thanks. T2C

rrmorales87 commented 6 years ago

Hi Aldeed, I need call a async method in options of select for autoform