$el.find(".detail").append("<div class='noImageDetail'>teest</div>");
But not working. Checked in devtools, not found any bug. How can I use append in Backbone? Also, how can I use if - else?
You don't have any errors on your code as it is, now you need to make sure that exists something inside of your "el" with the "detail" class, example
HTML
<div id="book">
<div class="detail">Book:</div>
</div>
JS
var BookView = Backbone.View.extend({
el: '#book',
initialize: function() {
this.render();
},
render: function() {
this.$el.find(".detail").append("<div class='noImageDetail'>teest</div>");
}
});
var bookView = new BookView();
You need to use this.$el.find('selector') you could also use this.$('selector') which will save you some keystrokes since it's basically and alias to this.$el.find
I wrote an example in this plunker
The if - else is basic JavaScript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else
Related
Handlebar conditionals actually delete the DOM elements inside of the conditionals, JQuery thinks that the newly generated DOM elements, despite their matching ID or class is something entirely different.
I need a simple solution for this. A solution that I can wrap my solutions in once per page. I don't want to have to tack .observes() after everything as that seems like a shoddy work-around
Right now I put my Jquery in the didInsertElement{} in my current view that is being used.
Simple Example:
exampleView -
didInsertElement {
$('#exampleButton').on('click', function() {
console.log('To Ember. Or to Angular. That is the question.')
}
}
example.hbs -
{{#if booleanTrue}}
<button id="exampleButton">Button go!</button>
{{/if}}
That approach is not best for Ember. For the future release of Ember they are planing to remove jQuery dependency. With Ember you don't have to use jQuery.
rewrite your code like this:
didInsertElement: function(){
this.$().hide().fadeIn('slow'); // or any animation that you want
},
actions: {
myButtonAction: function(){
//do something
}
}
{{#if booleanTrue}}
<button id="exampleButton" {{action "myButtonAction"}}>Button go!</button>
{{/if}}
willDestroyElement is not right hook for animation. So you have to trigger it yourself.
I use my custom action like
actions: {
deleteClicked: function(){
var self = this;
this.$().animate({ height: 'toggle' }, 300, function() {
self.set('booleanTrue', false);
});
}
}
due to your comment I changed my answer
I want to make a view for html document inside an iframe. For something like:
<div id="some">
<iframe id="other" />
</div>
I want to dynamically load an html document received from server into this iframe. The problem is, that I want to use Backbone View for that document. If I do something like this:
var projectView = Backbone.View.extend(
{
tagName: 'html',
initialize: function()
{
this.model.bind('sync', this.render, this);
},
render: function()
{
this.$el.html(this.model.get('content')); // content is from model, and it
//receives the html document from server
return this;
}
});
Then, when I do:
var iframe = $('#other')[0].contentWindow.document;
iframeDocument.open();
iframeDocument.write(projectView.render().el);
iframeDocument.close();
It does not work. I tryed a lot of different combinations but no success. If I use document.write() with static html it works fine but how to do with backbone view and dynamic content?
The "el" property is a reference to an HTML object. You're passing it into a document.write() call when that function is actually expecting an HTML string. Which is why static HTML works for you.
So you'd probably want to do something like this:
iframeDocument.open();
iframeDocument.write(projectView.render().el.innerHTML);
iframeDocument.close();
I think your approach is unnecessarily complex and using backbone isn't buying you anything useful. Why don't you just set the iframes src attribute with the model's content URL and be done with it?
render: function()
{
this.$el.attr('src', this.model.url()); //Or whatever you need to get the right URL
return this;
}
There is no reason to use an iframe.
You can just replace the iframe with a div and it will render every time your sync event is triggered.
You can also use on instead of bind for the event.
var projectView = Backbone.View.extend(
{
tagName: 'div',
initialize: function()
{
this.model.on('sync', this.render, this);
},
render: function()
{
this.$el.html(this.model.get('content')); // content is from model, and it
//receives the html document from server
return this;
}
});
and then just put the view into a container
$('#some').html(projectView.el);
you may have to remove some unnecessary content(ie. <head> tags) from the model whenever it syncs
Does anyone ever faced the integration of Etch.js in a Backbone.Marionette.js application?
I'm having issues binding the save event. This is the code for my Marionette view:
MyApp.module('Views', function(Views, App, Backbone, Marionette, $, _) {
Views.DetailsView = Marionette.ItemView.extend({
template: '#details',
initialize: function(options) {
_.bindAll(this.model, 'save'); // I think the problem is related to the binding
this.model.bind('save', this.model.save);
},
events: {
'mousedown .editable': 'editableClick'
},
editableClick: etch.editableInit
});
});
and in my template I have something like the following:
<div id="detail-expanded">
<p>Description: <span class="editable">{{ description }}</span></p>
</div>
The plugin is loaded correctly, if I click on the field I can see the Etch buttons bar, I can edit the content of the element made editable and if I click on the save button I'm actually able to trigger the model save() method.
The problem is that the model submitted is the original one, without the edits that I did to the field. I think it's a binding problem, any ideas?
Thanks in advance, as always.
So, the problem here is not really related to marionette, it's that etch doesn't handle moving the data from the editable field to the model. I should be more explicit about that in the docs. What you want to do is create a save function on the view that does this for you like so:
Views.DetailsView = Marionette.ItemView.extend({
template: '#details',
initialize: function(options) {
_.bindAll(this, 'save');
this.model.bind('save', this.save);
},
events: {
'mousedown .editable': 'editableClick'
},
editableClick: etch.editableInit,
save: function() {
// populate model attrs from dom
var title = this.$('.title').text();
var body = this.$('.body').text();
this.model.save({title: title, body: body});
}
});
Sorry for the confusion. I can see how the docs are misleading in this regard.
I believe what you want is
_.bindAll(this, 'save');
instead of
_.bindAll(this.model, 'save');
I'm using Backbone 0.9.2 and I have a mustache template that uses twitter bootstrap and looks something like this:
<div class="modal hide something" id="something-modal">
...
</div>
I tried getting rid of the extra <div> that backbone adds because I want the view to be 1-to-1 as my template. My render function looks something like:
render: function(){
var $content = $(this.template()),
existing_spots = $content.find('.spots-list'),
new_spot;
this.collection.each(function (spot) {
new_sweetspot = new SpotView({ model: spot });
existing_spots.append(new_spot.render().el);
});
$content.find("[rel=tooltip]").tooltip();
this.setElementsBindings($content);
//this.$el.html($content).unwrap('div'); // didn't work!
this.$el.html($content);
console.log(this.$el);
return this;
}
I know that by adding:
tagName: "div",
className: "modal",
I'll get rid of it, but I want the control of the view's elements to be of the template, not of the JS code.
this.SetElement will cause the list NOT to be updated (it'll be empty), this.$el = $content; won't work as well.
There was a good thread on this last week on SO.
Backbone, not "this.el" wrapping
tl;dr you can use setElement, but you really need to know when things happen in backbone to make sure everything is wired up correctly.
I'm working on converting a single-page app to backbone.JS. The View below uses the body tag as it's tagName - ie, I want the view to occupy the entire content of the page. I don't want to use container divs or other hacks.
var ThingView = Backbone.View.extend({
tagName : "body",
...
// Show the HTML for the view
render : function() {
console.log('Displaying thing')
$(this.el).append('<h1>test</h1>');
console.log('finished')
console.log($(this.el))
return this; // For chaining
When rendering, I see
finished
[
<body>
<h1>test</h1>
</body>
]
But after I inspect the DOM, the body no longer has the text.
tagName indicates what tag Backbone should use to create its el if no el is provided by the constructor. The created element is not automatically inserted into the DOM.
The simplest way is probably to create your view with its el set to body :
new ThingView({el:'body'})
What nikoshr explained is correct. Adding to it, Using tagName is correct. but Ideally you should use el element, which is defined in Backbone.js library as an element (el) of View.
Below is the ideal code you should use while doing this.
<script type="text/javascript">
$(document).ready(function(){
var ThingView = Backbone.View.extend({
el:$("body"),
initialize: function(){
_.bindAll(this,"render");
this.render();
},
render:function(){
this.el.append('<h1>test</h1>');
console.log('finished');
console.log($(this.el).html());
}
});
var ThingView = new ThingView();
});
</script>