Modal bootstrap disapear with change event meteor

2019-02-10 11:46发布

问题:

I use a modal with bootstrap, so I have a modal with 3 tabs. In one of this tab I have a select like this :

      <div class="modal-body">

        <ul class="nav nav-tabs" id="TabModal">
            <li><a href="#onglet1" data-toggle="tab">Libre</a></li>
            <li><a href="#onglet2" data-toggle="tab">Complexe</a></li>
            <li><a href="#onglet3" data-toggle="tab">Questionnaire</a></li>
        </ul>

        <div class="tab-content">
            <div class="tab-pane" id="onglet1">
                <span class="label label-primary">Choose your collections :</span><br /><br />
                {{>eachCollections}}

                {{#if collectionChoose 1}}
                    <label style="float:left;">Par : </label>
                    <select class="form-control" style="width:200px;float:left;" id="widgetFilterSelectPanelistes">
                        <option value="none">-- none --</option>
                        <option value="name">Name</option>
                        <option value="age">Age</option>
                        <option value="city">City</option>
                    </select>
                    {{>eachKeyPanelistes}}
                    {{#if panelistChoose "name"}}
                        <select class="form-control" style="width:200px;">
                            {{#each panelistes}}
                                <option value="{{name}}">{{nom}}</option>
                            {{/each}}
                        </select>
                    {{/if}}
                {{else}}
                    {{#if collectionChoose 2}}
                        <p>participants</p>
                    {{/if}}
                {{/if}}

In the modal I use a select and when I change the select value I show an other select etc ...

For this template I have a JS file like this :

Template.eachCollections.helpers({
collections : function () {
    return Collec.find();
}
});

Template.eachCollections.events({
'change #eachCollectionsSelect' : function () {
    var selected = document.getElementById('eachCollectionsSelect').value;
    Session.set('selectedCollections', selected);   
}
});

Template.widgetFilter.collectionChoose = function (param) {
return parseInt(Session.get('selectedCollections')) === param;
}

But when I trigge the event on the select change, the modal disepear...

Do you have a solution ?

回答1:

I think this scenario is happening under the hood :

  • You open (show) the modal with a javacript jQuery plugin call, which basically modifies the DOM (adding css classes and stuff to make the modal visible).
  • Then a change event occurs in the modal, which cause Meteor to rerender the modal AS IT WAS DEFINED IN THE TEMPLATE, wiping out the "shown" css classes.
  • This cause the modal to disappear because it is rerendered in the hidden state.

So what are the viable solutions ?

First, I'll have let you know that this particular part of Meteor is currently being rewritten by core developers (Meteor UI project) and in a near future (1-3 months) we'll have painless jQuery plugins integration, because Meteor DOM rerendering won't wipe the entire DOM anymore, the new engine is smart enough to leave modifications to DOM attributes untouched !

So basically your code might work painlessly in a near future BUT not everyone can be patient enough to wait, so here is the solution Meteor developers came up (they implemented it in the parties example).

You'll need another Session variable representing the state of the modal : shown/hidden. If the variable is true, then call the template for the modal IN THE SHOWN STATE, if it isn't do nothing. It means that you'll have to give up on modal transitions (fade in/out), but it will allow your modal template to rerender normally.

Here is the pattern code : (using Bootstrap 3 !)

modal template :

<template name="myModal">
    {{#if showModal}}
        <!-- this is the backdrop fully shown from the beginning -->
        <div class="modal-backdrop fade in"></div>
        <!-- css ".show" class == modal fully shown -->
        <div class="modal show">
            <div class="modal-dialog">
                <div class="modal-content">
                    <form class="form-horizontal">
                        <div class="modal-header">
                            <button type="button" class="close" aria-hidden="true">&times;</button>
                            <h4 class="modal-title">Modal Title</h4>
                        </div>
                        <div class="modal-body">
                            Modal Body
                        </div>
                        <div class="modal-footer">
                             <button type="button" class="cancel btn btn-default">Cancel</button>
                             <button type="submit" class="btn btn-primary">Submit</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    {{/id}}
</template>

modal javascript :

Template.myModal.created=function(){
    Session.set("show-my-modal",false);
};

Template.myModal.helpers({
    showModal:function(){
        return Session.get("show-my-modal");
    }
});

Template.myModal.events({
    "click .close, click .cancel":function(){
        Session.set("show-my-modal",false);
    },
    "submit form":function(event){
        event.preventDefault();
        //
        Session.set("show-my-modal",false);
    }
});

parent template :

<template name="parent">
    {{> myModal}}
    <button class="show-my-modal-button" type="button">
        Show Modal
    </button>
</template>

parent javascript :

Template.parent.events({
    "click .show-my-modal-button":function(){
        Session.set("show-my-modal",true);
    }
});