Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema reactivity #802

Closed
elGusto opened this issue Mar 21, 2015 · 18 comments
Closed

Schema reactivity #802

elGusto opened this issue Mar 21, 2015 · 18 comments

Comments

@elGusto
Copy link

elGusto commented Mar 21, 2015

I have a quickForm rendered with the schema option and my schema is constructed from a reactive-var. Very much like the code in the autoform-demo package.

It is almost working but I am experiencing an error when a field is removed from the schema.
Adding fields works like a charm but removing it throws error for every autoform template related to the field being removed.

Exception in template helper: Error: Invalid field name: 7e36a84b8ceb597e95717ff9
    at Object.getDefs (http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:257:13)
    at Object.autoFormGetComponentContext [as getComponentContext] (http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:532:20)
    at Object.afQuickFieldIsGroup (http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:7238:30)
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:2786:16
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:1607:16
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:2834:66
    at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:3382:12)
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:2833:27
    at Object.Spacebars.call (http://localhost:3000/packages/spacebars.js?7bafbe05ec09b6bbb6a3b276537e4995ab298a2f:172:18)
    at http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:7189:22
debug.js:41 Exception in template helper: Error: Invalid field name: 7e36a84b8ceb597e95717ff9
    at Object.getDefs (http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:257:13)
    at Object.autoFormGetComponentContext [as getComponentContext] (http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:532:20)
    at Object.afQuickFieldIsFieldArray (http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:7244:30)
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:2786:16
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:1607:16
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:2834:66
    at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:3382:12)
    at http://localhost:3000/packages/blaze.js?4e49999979a58da0e2265f7bd3f5910f9901b07b:2833:27
    at Object.Spacebars.call (http://localhost:3000/packages/spacebars.js?7bafbe05ec09b6bbb6a3b276537e4995ab298a2f:172:18)
    at http://localhost:3000/packages/aldeed_autoform.js?5078663143adf2fce70916f147f7080a0634563d:7194:24

And this goes on...
I thought my error was related to #794 but I still have the error after the update this morning.

Should I use the workaround trick you used in the autoform-demo package ?

@aldeed
Copy link
Collaborator

aldeed commented Mar 21, 2015

Yes, you probably still need the workaround. The error can sometimes appear in the demo pkg, too. At some point I can probably make it work properly, but it's difficult to debug the blaze reactivity stuff.

@Gigacross
Copy link

Hi @elGusto,

which workaround trick are you referring to?

@elGusto
Copy link
Author

elGusto commented Mar 23, 2015

@Gigacross I am talking about this https://github.com/aldeed/autoform-demo/blob/master/client/views/quickform/quickform.html#L57-L59

Based on the code that you provided, I am not able to tell what you are doing wrong. Are you giving the schema to autoform with a helper using your reactiveVar.get()?

@aldeed Alright thanks for the tip! Yeah I started doing that but quickly gave up since I just started to get into blaze with arunoda's book.

@Gigacross
Copy link

@elGusto Thanks! I implemented that work around but I'm still getting errors, not entirely sure where I went wrong... basically the idea is to delete the whole form, and recreate it.

I managed to find out how it was implemented after looking at the example code provided in the demo, so I managed to successfully implement dynamic schema, hence I removed my reply here. But now I don't know how to change the key / rename the title of the key i.e. { name : { type : String }}, do you have a recommended way of renaming name reactively?

I think I have to make a full layer between user and making the schema, so basically user -> buildSchemaPkg -> generate schema -> feed into autoform, all my attempts to create a dynamic form properly has been futile... that way autoform don't really have to deal with all the reactivity also...

@elGusto
Copy link
Author

elGusto commented Mar 23, 2015

@Gigacross I am also working on the exact thing. I didn't get there yet but will later today if all is good.

I will update here when I can really give you an answer.

@Gigacross
Copy link

@elGusto Cool! In the meantime I'll also attempt to create that myself, may be not build into a full package, but I'll be able to put a gist together or something, if you happen to accomplish it before I do, let me know! Thanks in advance :)

@abecks
Copy link
Contributor

abecks commented Mar 24, 2015

The workaround is no longer working for me on version 5. I'll see if I can track down a fix.

@abecks
Copy link
Contributor

abecks commented Mar 24, 2015

Nevermind, the concept of the workaround still works for me. I ended up making the schema a ReactiveVar so I can control when it changes. First I set destroyForm to true, which will cause the template to remove the existing autoForm from the DOM, then I set the schema var to the NEW schema, and then the second computation fires to set destroyForm back to false.

It still feels horrible doing it this way, as the timing is ambiguous but this pattern seems to be working for me.

<template name="stepView_form">
    {{#if destroyForm}}
    {{! this is a wonky workaround for the fact that autoform doesn't handle reactively changing schema attribute, which should be fixed eventually}}
    {{else}}
        {{#autoForm id="stepViewForm" schema=schema doc=answers resetOnSuccess=false}}
            {{#each afFieldNames}}
                {{> afQuickField name=name options=afOptionsFromSchema}}
            {{/each}}
        {{/autoForm}}
    {{/if}}
</template>
var currentStep;
var destroyForm = new ReactiveVar(false);
var schema = new ReactiveVar(null);

Template.stepView_form.created = function(){
  schema.set(getSchema(this.data.step));

  this.autorun(function(){
    var step = Template.currentData().step;

    if(step.slug !== currentStep){
      destroyForm.set(true);
      currentStep = step.slug;
      schema.set(getSchema(step));
    }
  });
};

Template.stepView_form.rendered = function(){

  this.autorun(function () {
    if (destroyForm.get()) {
      destroyForm.set(false);
    }
  });
};

Template.stepView_form.helpers({

  destroyForm: function(){
    return destroyForm.get();
  },

  /**
   * Create a SimpleSchema to represent the step
   */
  schema: function(){
    return schema.get();
  }
});

function getSchema(step){
  // this function builds a schema object, I removed the code for simplicity
  return new SimpleSchema(schema);
}

@elGusto
Copy link
Author

elGusto commented Mar 31, 2015

Yep this is it but I still get the errors like before, the workaround didn't correct the bug which occurs only when a field is removed from the schema.

I made a package to create autoform schemas with the UI. The goal is to provide a simple form builder that then could be used to create some sort of CMS system. It is still in the (very) early stage but I will publish it soon enough when I have time to clean some stuff out.

@abecks
Copy link
Contributor

abecks commented Mar 31, 2015

Ive built a similar AF schema builder in a proprietary app I'm making.
Maybe when you are done we could tackle the schema reactivity bugs together.
On 31 Mar 2015 08:05, "Gus" notifications@github.com wrote:

Yep this is it but I still get the errors like before, the workaround
didn't correct the bug which occurs only when a field is removed from the
schema.

I made a package to create autoform schemas with the UI. The goal is to
provide a simple form builder that then could be used to create some sort
of CMS system. It is still in the (very) early stage but I will publish it
soon enough when I have time to clean some stuff out.


Reply to this email directly or view it on GitHub
#802 (comment)
.

@abecks
Copy link
Contributor

abecks commented May 26, 2015

I have prepared a branch of autoform that allows for the schema to be reactive.

It's not an ideal solution, but this may work for our needs. I would appreciate any help you can provide in testing the branch. I wouldn't recommend it for production until it is tested further.

https://github.com/abecks/meteor-autoform/tree/reactive-schema

Using this branch, you can return a SimpleSchema object to the schema attribute of a form (via a helper), and the form will re-render without errors.

<template name="form">
    <button data-schema="schemaOne" class="btn btn-change-schema">One</button>
    <button data-schema="schemaTwo" class="btn btn-change-schema">Two</button>

    {{> quickForm schema=formSchema doc=this id="testForm"}}
</template>

Schema = {
  schemaOne: new SimpleSchema({
    name: {
      type: String
    },
    options: {
      type: String,
      autoform: {
        options: function () {
          return {
            'Test': 'test',
            'Test2': 'test2'
          }
        }
      }
    }
  }),
  schemaTwo: new SimpleSchema({
    phone: {
      type: String
    }
  })
};


if (Meteor.isClient) {
  Session.setDefault('formSchema', 'schemaOne');

  Template.form.helpers({
    formSchema: function () {
      return Schema[Session.get('formSchema')];
    }
  });

  Template.form.events({
    'click .btn-change-schema': function (e) {
      var $btn = $(e.target);
      var schema = $btn.data('schema');

      Session.set('formSchema', schema);
    }
  });
}

I've made as few changes as possible. The problem lies in how the AutoForm context is passed around to field template helpers. Field's grab their "AutoForm context" from calls to AutoForm.getSchemaForField or AutoForm.Utillity.getComponentContext, both of which rely on AutoForm.getCurrentDataForForm. getCurrentDataForForm retrieves the data using Blaze.getData. This means that all template helpers have a reactive dependency on the data context of the form itself.

A change in schema will cause all of the fields in the form to re-render. The problem is that the helper's reactive dependency on Blaze.getData triggers BEFORE the re-rendering of the form fields. This causes all sorts of errors as the field's try to look up their data context again, as they don't exist in the new schema.

My branch adds a few checks and try/catch enclosures to prevent fields from throwing errors when they no longer exist in the schema.

@cwaring
Copy link

cwaring commented Aug 5, 2015

I've just ran across a similar issue when changing the schema reactively, I assume this fix hasn't made it into core yet @abecks?

@abecks
Copy link
Contributor

abecks commented Aug 5, 2015

Not yet. Sorry guys. Will try to resubmit my PR soon. You can always take
my reactive schema branch for yourself.
On Aug 5, 2015 11:52 AM, "Chris Waring" notifications@github.com wrote:

I've just ran across a similar issue when changing the schema reactively,
I assume this fix hasn't made it into core yet @abecks
https://github.com/abecks?


Reply to this email directly or view it on GitHub
#802 (comment)
.

@abecks
Copy link
Contributor

abecks commented Aug 13, 2015

Resubmitted my PR, watch #1132 for updates.

@cwaring
Copy link

cwaring commented Aug 13, 2015

@abecks 👍 thanks man!

@bySabi
Copy link
Contributor

bySabi commented Sep 18, 2015

@abecks any new with this PR?
Thanks

@bySabi
Copy link
Contributor

bySabi commented Sep 18, 2015

Update and revive @abecks PR(#1132) here: #1205

@aldeed
Copy link
Collaborator

aldeed commented Oct 6, 2015

PR has been merged. Will release new version soon.

@aldeed aldeed closed this as completed Oct 6, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants