Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rendered called before DOM completion - meteor blaze

I am creating a dynamic form using json and trying to use jquery-validation plugin to add validation rules to input fields.

Json structure and helper method is :

var fields = [{
    label: "Name",
    type: {name: 'STRING'},
    validationRules: {
        required: true,
        maxlength: 100,
        minlength: 3
    }
},{
    label: "Currency",
    type: {name: 'CHECKBOX'},
    defaultValue: ['USD', 'INR'],
    validationRules: {
        required: true
    },
    sourceCollection: 'oNLFfi4L3zgNLhScv',
}] ;

Template.eventCreate.helpers({
    fields: function(){
        console.log("calling fields");
        fields.forEach(function(field, index){
            field.sourceCollectionData = StaticLists.find({_id: field.sourceCollection});
        });
        return fields;
    }
});

Template looks like:

<template name="eventCreate">
    <form id="newEventForm" class="form-horizontal">
        {{#each fields}}
            <div class="form-group">
                <label class="col-xs-2 control-label">{{label}}</label>
                <div class="col-xs-6">
                    {{#if equals type.name 'STRING'}}
                        <input name="{{label}}" id="{{label}}" class="form-control" placeholder="Enter {{label}}" value="{{defaultValue}}" />
                    {{/if}}
                    {{#if equals type.name 'CHECKBOX'}}
                        {{#each sourceCollectionData}}
                            {{#if isActive}}
                                <div class="col-xs-2 checkbox">
                                    <label class="checkbox-inline">
                                        <input type="checkbox" name="{{../label}}" id="{{../label}}" value="{{name}}" {{checked ../defaultValue}}> {{name}}
                                    </label>
                                </div> 
                            {{/if}}                               
                        {{/each}}                         
                    {{/if}}
                </div>               
            </div>
        {{/each}}
    </form>
</template>

Now I am trying to add validation rule in rendered method:

Template.eventCreate.rendered = function(){
    $('#newEventForm').validate({
       ....
    });

    fields.forEach(function(field, index){
        if(field.validationRules){
            $('#'+field.label).rules('add', field.validationRules);
        }
    });
}

It works in case of input text but throws exception for checkbox because checkbox DOM is still not laid out and there is no element with id "Currency".

I assume in meteor blaze rendered is called once only when DOM rendering is complete. Though it is called once here but before DOM rendering completes.

EDIT

Earlier I was hardcoding the JSON in js file itself and now I am retrieving it from mongo.

But its seems that rendered callback is invoked only first time and not invoked every time mongo collection changes(which in turn updates the DOM)

Template.eventCreate.helpers({
    fields: function(){
        var template = EventTemplate.findOne({name: 'Job Template'});
        console.log("template", template);
        if(template){
            Session.set("template", template);
            template.fields.forEach(function(field, index){
               field.sourceCollectionData = StaticLists.find({_id: field.sourceCollection});
            });
            return template.fields;
        }        
    }
});

Template.eventCreate.rendered = function(){
    $('#newEventForm').validate({
        ...
        ...
    console.log("rendering main template");

   addValidationRules(Session.get('template'));
}

Now the console output is something like:

template undefined event_create.js?bfeba9389401dac358bc313bd9d4205818e356a1:52
rendering main template event_create.js?bfeba9389401dac358bc313bd9d4205818e356a1:98
template Object {_id: "iFDndmjavtFN8AdGQ", name: "Job Template", description: "Job Template",     fields: Array[13]}

which shows that (and I tried it even with a break point in js script) that just when script loads template is undefined and no input field is rendered on front end but rendered callback is invoked. Now later when template gets populated with data, input fields are rendered but callback is not invoked again.

like image 788
Aashu Avatar asked Nov 11 '22 10:11

Aashu


1 Answers

The recommended pattern is to put the contents of your {{#each}} blocks in separate templates and tap into the rendered event of those templates.

By the way, Meteor.defer is no longer required.

like image 79
0x6A75616E Avatar answered Nov 14 '22 23:11

0x6A75616E