问题
I am trying to get modals to consistently work with Meteor. They have this problem of disappearing when data context values change. I've already solved a portion of this problem, as documented by this question, but now it's back, and it's happening when values in the surrounding template change, rather than values in the template.
Here's the actual modal:
<div class="modal fade" id="paymentModal" tabindex="-1" role="dialog" aria-labelledby="paymentModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="paymentModalLabel">Make a Payment</h4>
</div>
<div class="modal-body">
{{> paymentModalBody}}
</div>
<div class="modal-footer">
{{> paymentModalFeedback}}
</div>
</div>
</div>
</div>
The modal works fine when the values changing are inside of it (or in other words, when paymentModalBody
or paymentModalFeedback
have changing values, since those template re-renders don't cause the main modal elements to be re-rendered), but....
this is happening inside my userView
template, which displays information about a user (duh). The modal handles payment interaction with the user, and calls a Meteor.method
called...
makeBraintreePayment: function(saleObj) {
var now = new Date();
Gateway.transaction.sale(saleObj, Meteor.bindEnvironment(
function (err, result) {
if (result.success) {
if (result.transaction.customer.id && saleObj.options.storeInVaultOnSuccess) {
Meteor.users.update(Meteor.userId(), {$set: { braintree_id: result.transaction.customer.id }});
}
var paymentId = Payments.insert({ ... });
Meteor.users.update(Meteor.userId(), {$push: { 'payment_ids': paymentId }});
return result.transaction.id;
} else {
throw new Meteor.Error(401, result.message);
}
},
function(err) {
console.log('bind failure: ' + err.message);
}
));
}
now again, all of this works just fine, but, after the payment is made and the modal has displayed the success message, after a second or two the modal disappears and leaves only the background, locking out the user and making it necessary to refresh the page. Broken.
It's pretty clear to me that this is happening because of those Meteor.users.update
calls, since they're changing the data context of the userView
template, which is causing the modal template to be re-rendered. So, I tried to use preserve
:
Template.userView.preserve(['#paymentModal', '.modal-dialog', '.modal-content', '.modal-header', '.modal-body', 'modal-footer', '.modal-title', '.close']);
and this:
Template.userView.preserve(['#paymentModal']);
Neither worked. This should be maintaining the html for all of the static modal elements, while allowing everything around it to be re-rendered, but it doesn't.
What's going on? How to I solve this?
Thanks in advance!
P.S.
I have been trying to solve this problem by using a more stable modal library, bootboxjs
, but I've had a different problem with that. If you can offer some insight on either that would be awesome!
回答1:
Put your modal in an {{#isolate}}
block as well.
{{#isolate}}
<div class="modal fade" id="paymentModal" tabindex="-1" role="dialog" aria-
...
</div>
{{/isolate}}
This way, if something changes outside it will be ignored as well as inside it.
Something better may be to consider upgrading to using the Blaze RC (running meteor --release blaze-rc1 update
) which uses fine grained DOM patching to avoid this issue. And plays well with Bootstrap and other jquery plugins.
The difference is Spark (the current rendering engine) replaces the entire DOM when there is a change, where Blaze is designed to change only the element which has changed.
来源:https://stackoverflow.com/questions/22439172/meteor-modal-is-disappearing-and-locking-out-the-user