Meteor-AutoForm: How to update select options based on another control
Asked Answered
P

2

6

I've been trawling SO questions for an answer to something that should be very simple but for the life of me I cannot figure it out.

Basically I have a meteor-autoform with two select controls:

<template name="processFormTemplate">
    {{#autoForm id="processForm" collection="Processes" type=formAction doc=doc validation="blur"}}
        <div class="col-md-12">
            {{> afQuickField name="elementId" options=elements}}
            {{> afQuickField name="categoryId" options=categories}}
            {{> afQuickField name="title"}}
            {{> afQuickField name="desc" rows=4}}
        </div>
        {{>formButtons}}
    {{/autoForm}}
</template>

These then have helpers to populate the options:

Template.processFormTemplate.helpers({
  elements: function() {
    return getFormElements();
  },
  categories: function(elementId) {
    return getFormCategories(this.doc.elementId);
  }
});

lib/methods.js

 getFormElements = function() {

        var options = [];

    Elements.find({}, {sort: {ref:1}}).forEach(function (element) {
                    options.push({
                        label: element.title, value: element._id
                    });
                });

    return options;

};

getFormCategories = function(elementId) {

    var options = [];
    var filter = {};

    if (!isBlank(elementId)) {
        filter.elementId = elementId;
    }

    Categories.find(filter, {sort: {ref:1}}).forEach(function (d) {
                    options.push({
                        label: d.title, value: d._id
                    });
                });

    return options;

};

Now I know this isn't working because the helper isn't reactive, however I don't know how to change this behaviour. I've also tried hooking into the 'change' event but this never fires for some reason:

Template.processFormTemplate.events({
 'change #elementId': function(e) {
  console.log($('[name="elementId"]').val() + ' is now selected');
}
});

The required behaviour is that when a new elementId is selected in the first list, the list of options in the second should be refreshed based on the selected elementId.

Any help much appreciated.

Thanks, David

Passmore answered 23/2, 2015 at 22:54 Comment(0)
P
13

I had the same problem before that took me hours to resolve. You have to use simple schema to get the value of selected option like this using autoform's api call Autoform.getFieldValue:

Schemas.Store = new SimpleSchema({
center: {
    type: String,
    optional: true,
    autoform: {
        type: "select",
        options: function () {
            return Centers.find().map(function (c) {
                return {label: c.name, value: c._id};
            });
        }
    }
},
region: {
    type: String,
    optional: true,
    autoform: {
        type: "select",
        options: function () {
            if (Meteor.isClient) {
                var docId = '';

                docId = AutoForm.getFieldValue('storesForm', 'center');


               return Regions.find({center: docId}).map(function (c) {
                   return {label: c.name + ' (' + c.code + ')', value: c._id};
               });
            }
        }
    }
}, 
store_name: {
    type: String
} 
});

BTW, I'm still using [email protected] due to issues encountered when using Autoform.getFieldValue in 5.0

Issue in 5.0.3 I've reported to aldeed: https://github.com/aldeed/meteor-autoform/issues/785#issuecomment-84600515

Palate answered 23/3, 2015 at 3:43 Comment(4)
hi there - thanks for the answer... how would you use your solution across multiple forms requiring the same behaviour?Passmore
@Palate Curious as to why you have if (Meteor.isClient()) in your Region autoform options function... ?Ducks
@Ducks it's because getFieldValue is a client only API call of autoform. :) Here: github.com/aldeed/meteor-autoform/blob/devel/…Palate
thanks... I'm just trying to get my head around things like autoform options functions, and when they run.. if I put a console.log in my autoform options function, generally, I only see the log statement shown on the client, but sometimes I see that log statement show up on the server...odd to me, that's all!Ducks
P
5

I've managed to get this working - couple of things were wrong:

  1. I needed to add an 'id' to the first select control so i could capture it's change event:

        {{> afQuickField name="elementId" id="elementId" options=elements}}
    

I then used a Reactive Dict variable which I then set in the changed event. A session variable would probably do the same job.

Template.processFormTemplate.events({
 'change #elementId': function() {
  dict.set('activeElementId', $('select#elementId').val());
}
});

and use this as a parameter in my categories helper:

  categories: function(elementId) {
    return getFormCategories(dict.get('activeElementId'));
  }

Hopefully this helps anyone else having a similar issue.

Passmore answered 23/2, 2015 at 23:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.