I'm trying to use backbone js to implement a Modal window, but when I run the code, it does the search every time. I thought that I could just create a variable and assign it a 1 or 0, and check for that in my code, but I can't seem to access it properly.
Here are my two files: ModalView.js
var modalTemplate = "<div id=\"pivotModal\" class=\"modal\">" +
"<div class=\"modal-header\"><h3><%- title %></h3><button class=\"dtsBtn close\">Close</button></div>" +
"<div class=\"modal-body\"><h3>Are you sure you want to remove <strong>all</strong> results from your query?</h3></div>" +
"<div class=\"modal-footer\"><button " +
"class=\"dtsBtn cancel\">Cancel</button><button " +
"class=\"dtsBtn confirm\">Confirm</button></div>" +
"</div>" +
"<div class=\"modal-backdrop\"></div>";
var ModalView = Backbone.View.extend({
defaults: {
title: 'Not Set',
isConfirmed: '0'
},
initialize: function (options) {
this.options = options;
this.options = _.extend({}, this.defaults, this.options);
this.template = _.template(modalTemplate);
console.log('Hello from Modal View: ' + this.options.title);
},
events: {
'click .close': 'close',
'click .cancel': 'cancel',
'click .modal-backdrop': 'close',
'click .confirm': 'confirm',
},
render: function () {
var data = {title: this.options.title}
this.$el.html(this.template(data));
return this;
},
show: function () {
$(document.body).append(this.render().el);
},
close: function () {
console.log('Closed');
this.unbind();
this.remove();
},
cancel: function () {
console.log('Cancelled');
this.unbind();
this.remove();
},
confirm: function () {
console.log('Confirmed');
this.options.isConfirmed = 1;
console.log(this.options.isConfirmed)
this.unbind();
this.remove();
}
});
modal_test.js (which runs the code above):
$('.clearAll').on("click", function(e) {
e.preventDefault();
var _title = "Confirm Action";
//pass the value of the item we clicked on to the title variable
var modal = new ModalView({ title : _title });
modal.show();
if (modal.isConfirmed === 1) {
console.log("Confirmed equals 1")
clearAllSearch.startSearch();
masterSearch.startSearch();
}
});
Everything works independently, but I can't get the if statement to run.
A way to implement a modal is to pass a callback function to the view.
ModalView.show({
title: _title,
callback: function(confirmed) {
if (!confirmed) return; // early return
console.log("User confirmed")
clearAllSearch.startSearch();
masterSearch.startSearch();
}
});
Where the view would be implemented like this:
var ModalView = Backbone.View.extend({
template: _.template(modalTemplate),
events: {
'click .close': 'close',
'click .cancel': 'close',
'click .modal-backdrop': 'close',
'click .confirm': 'confirm',
},
initialize: function (options) {
this.options = _.extend({ title: 'Are you sure?' }, options);
},
render: function () {
this.$el.html(this.template(this.options));
return this;
},
show: function () {
$(document.body).append(this.render().el);
return this;
},
close: function () {
this.remove();
var cb = this.options.callback;
if (cb) cb(false);
},
confirm: function () {
this.remove();
var cb = this.options.callback;
if (cb) cb(true);
}
}, {
// Static function
show: function(options) {
return new ModalView(options).show();
}
});
Instead of a callback, you could also use a Promise but it's not available in all browsers yet. An easy alternative would be to use jQuery deferred, jQuery's implementation of promises.
initialize: function(options) {
this.options = _.extend({ title: 'Are you sure?' }, options);
this.deferred = $.Deferred();
},
show: function () {
$(document.body).append(this.render().el);
return this.deferred;
},
close: function () {
this.remove();
this.deferred().reject();
},
confirm: function () {
this.remove();
this.deferred().resolve();
}
It would standardize the way the async confirmation is handled.
ModalView.show({ title: _title }).then(function() {
console.log("User confirmed")
clearAllSearch.startSearch();
masterSearch.startSearch();
});
It looks like you're calling modal.isConfirmed
but the modal view class is putting isConfirmed
into an options
property.
this.options = _.extend({}, this.defaults, this.options);
It would probably return the correct value if you used modal.options.isConfirmed
but you could possibly create a simple accessor function on the view.
isConfirmed: function() {
return this.options.isConfirmed;
}
And since isConfirmed
is a boolean flag, you should set it to true
, not an arbitrary integer like 0
or 1
.
Then you could call if (modal.isConfirmed())
and it would return the correct value.
Though, you're having another problem: the moment the modal is shown and the moment the user has interacted with the modal are asynchronous.
var modal = new ModalView({ title : _title });
modal.show();
// This will always be false since the user hasn't clicked anything yet.
if (modal.isConfirmed === 1) {
This is fixed with the callback technique shown first.
You're creating the template function each time you instantiate the modal view when you could do it once while defining the class.
var ModalView = Backbone.View.extend({
template: _.template(modalTemplate), // define the template here
initialize: function (options) {
// this.options = options; // useless line
this.options = _.extend({}, this.defaults, options);
},