Backbone.Marionette - show method not rendering properly.. somethings goes wrong - backbone.js

In my app, I am getting the show method issue. something is wrongly going on with my app. But i couldn't able to find that.
in case if i do like this my view is properly rendering ( but this is wrong approach ):
regions:{
header:'header',
content:'section',
footer:'footer'
},
initialize:function(){
console.log('initialized by layout')
},
renderRegions:function(options){
this.formData = _.defaults(options || {}, requireViews);
if(this.formData.headerView){ //this is true.
this.headerView();
this.renderHeaderView();
}
},
headerView:function(){
this.appHeaderView = new AppHeaderView({model:this.model});
return this.appHeaderView;
},
renderHeaderView:function(){
$(this.header.el).html(this.appHeaderView.render().el) //working fine
//but this is not workig: this.header.show(this.appHeaderView)..why not working?
}
why i use the "this.header.show" - nothing is appending to header.
Any one highlight me what is wrong i do here?
I have simplified my total process, and added in Jsfiddle here is the link:
Live Demo Here

You have a few issues in your code:
A view's model needs to be instantiated, not just the model class.
There is absolutely no reason for you to overwrite the ItemView's render method with what you had.
Your order of operations is wrong. show can only be called after the Layout is in the DOM already.
Here's the main thing that fixes your issue:
var Controller = Backbone.Marionette.Controller.extend({
initialize:function(){
this.layout = new Layout;
$('#wrapper').html(this.layout.render().el);
this.layout.renderRegions();
}
});
Updated FIDDLE
Another option (and something I find myself doing often) is to render the regions using the onShow method of the layout.

Related

HandsOnTable editor custom function

I'm using the autocomplete editor of HOT, but needed to have my own template of the option-list. I've been able to accomplish that, by removing the default display and replacing it with my own while doing a lazy load of its content. But I need to perform specific tasks on each of the options being clicked.
The issue is that I cannot find a way to have my <a ng-click='doSomething()'> or <a onclick = 'doSomething()'> tags to find my "doSomething" function.
I've tried the extend prototype of the autocomplete instance, have put my function out there on my controller to no avail. Is there any way I can insert a delegate function inside this editor that could be triggered from inside my custom-made template? (Using angularjs, HOT version 0.34)
Dropdown options cannot interpret HTML instead of Headers.
To perform action when an option is selected you can use Handsontable callback : AfterChange or BeforeChange
Here you can find all HOT callbacks https://docs.handsontable.com/0.34.0/tutorial-using-callbacks.html
This JSFiddle can help you http://jsfiddle.net/fsvakoLa/
beforeChange: function(source, changes){
console.log(source, changes)
},
afterChange: function(source, changes){
console.log(source, changes);
if(!source) return;
if(source[0][1] == 0){//if ocurs on col 0
let newsource = optionsWBS[source[0][3]];
cols[1] = {
type : 'dropdown',
source: newsource,
strict: false
};
hot.updateSettings({columns: cols});
hot.render();
};
}
Thanks, I actually needed actions specific to each area being clicked. What I did to make it work was this: while inserting the items for the list, I created the element and bound it to the function right away: liElement = document.createElement('li') .... liElement.onclick = doSomething(){} .... got it working this way ..

Unable to render a Ext.form.TextField into the output of an XTemplate

I want to render some Ext components into the output of an XTemplate. We want to have the flexibility of using an XTemplate to render the HTML but retain the styling, behaviour, and handlers of using Ext components rather than plain old HTML elements.
I am currently successfully doing this with an Ext.Button. In the template I am writing a placeholder div like so:
<div id="paceholder-1"></div>
After I have called apply() on the template I then create a new Ext component and render it in like so:
this._replacePlaceholders.defer(1, this, [html, 'placeholder-1', collection]);
The _replacePlaceholders function looks like this:
_replacePlaceholders: function(html, id, collection) {
var emailField = new Ext.form.TextField({
emptyText: 'Email address',
hideLabel: true
});
var downloadButton = new Ext.Button({
text: 'Download as...',
icon: 'images/down.png',
scope: this,
menu: this._createDownloadOptionsMenu(collection) // Create Menu for this Button (works fine)
});
var form = new Ext.form.FormPanel({
items: [emailField, downloadButton]
});
downloadButton.render(html, id);
}
This works and renders the button into the html correctly. The button menu behaves as expected.
But if I change the last line of replacePlaceholders to emailField.render(html, id); or form.render(html, id); I get a javascript error.
TypeError: ct is null
ct.dom.insertBefore(this.el.dom, position);
ext-all-debug.js (line 10978)
I'm a bit confused because from what I can tell from the docs the render() method called is going to be the same one (from Ext.Component). But I've had a bit of a play around and can't seem to track down what is happening here.
So is there any good reason why these components behave differently from Ext.Button? and is it possible to render an Ext.form.TextField or an Ext.form.FormPanel or anything that will let me use an Ext text field in mt XTemplate html?
NB. I am using ExtJS 3.3.1 and don't have the opportunity to upgrade the version. I believe ExtJS 4 has functionality which would make doing what I doing much easier.
Thanks!
Solution is quite simple - use form.render(id) instead of form.render(html, id).
See [api][1] if you have doubts.
The reason why button is rendering properly is that it has weird onRender implementation, different from Component.
onRender : function(ct, position){
[...]
if(position){
btn = this.template.insertBefore(position, targs, true);
}else{
btn = this.template.append(ct, targs, true);
}
[...]
}
As you can see in code above, if you provide position (which is basically second argument provided to render) it doen't use ct (which is first argument passed to render).
In normal component onRender method looks like this:
onRender : function(ct, position){
[...]
if(this.el){
this.el = Ext.get(this.el);
if(this.allowDomMove !== false){
ct.dom.insertBefore(this.el.dom, position);
if (div) {
Ext.removeNode(div);
div = null;
}
}
}
}
In code above, you can see, that ct is called always, despite the position is not null.
The bottom line is that rendering of button works by accident.

Backbone multiple view render stack?

There are a lot of similar answers to my question, but no what I want. My problem is:
I render view in backbone router. One screen is build with three views and since rendering is async and I append every view to #content element I cant control the order of rendered elements. Any ideas? I don't want to mix rendering of views in other views. I want to control that in router class.
Without seeing your code you do a couple things. If you wanted to drop in Marionette.js, you could use events to let your router know when it has rendered it.
App = new Marionette.Application(); // somewhere before you initialize your rotuer
// in your router
var viewsToRender = 3;
var view1El = new View({model: someModel}).render().el;
var view2El = new View({model: someModel2}).render().el;
...
App.vent.on('viewRendered', function() {
viewsToRender -= 1;
if(viewToRender === 0) {
$('#content').append(view1El, view1E2, ...);
}
});
// In your views
onRender: function() {
App.vent.trigger('viewRendered');
}
onRender documentation
Or you could move the fetching of your async data outside of your views and into the router(the route I would probably take).

Marionette CollectionView: how to check whether item is added because of "reset" or "add"?

I am using Marionette's CollectionView to render a list of items with ItemViews. Whenever a new item is added, I want to run a short fade-in animation. But not when the collection is rendered initially (or the collection is reset).
Before using Marionette, I handled the reset and add events slightly differently, but I can not figure out how to do this here. I looked at the source code and it seems that addItemView is responsible for adding the child view and both addChildView (called when add is triggered on the collection) and render (for reset events) call this method.
Maybe I am missing something obvious.
This is one way of doing it:
Include these functions in your CompositeView declaration:
onBeforeRender: function(){
this.onBeforeItemAdded = function(){};
},
onRender: function(){
this.onBeforeItemAdded = myAnimation;
}
This is similar to the solution I present in my book on Marionette (https://leanpub.com/marionette-gentle-introduction/)
How it works: Marionette triggers the "before:render" before it renders the entire collection, so you can set the the onBeforeItemAdded function to do nothing. Once the collection has been rendered, set that function to animate the new item view.
Since each time the collection view adds an item view it also triggers the "before:item:added", you can define an onBeforeItemAdded function that will automatically be called when that event is triggered. This matching happens thanks to triggerMethod.
This solution should solve your problem, without your needing to add flags on the model.
David Sulc answer is pretty hacky, fadeIn should be defined within item it self, not within parent view.
Another thing is that onBeforeItemAdded() is not mentioned in documentation, so it could be for internal use and may change over time.
What I suggest is to add following to parent view, note flag parentRendered:
itemViewOptions: function() {
return {
collection: this.collection,
parentRendered: this.rendered
};
},
onRender: function() {
this.rendered = true;
}
and use that flag in onShow function inside item view:
onShow: function() {
// show visual effect on newly added items
if (this.options.parentRendered) {
this.$el.css('opacity', 0).slideDown(200).animate(
{ opacity: 1 },
{ queue: false, duration: 400 }
);
}
else {
this.$el.show();
}
}
I think that your best choice is to bind your event after the CollectionView has been rendered.
myCollectionView.on( "render", function() {
this.on( "after:item:added", executeMyAnimation );
});

extjs 3 - Which event is fired when extjs is completely loaded

I am using Extjs for my application. Which event/listener is fired when extjs completely loads the application (images and everything)?
I tried following but none of these worked:
body or window onload (body tag is empty)
viewport render listener
What I am doing currently: When I start the application it displays "loading" mask. Then an ajax request is fired and when it is completed, "loading" mask is removed. Following might give some idea:
Ext.onReady(function(){
Ext.ux.mask = new Ext.LoadMask(Ext.getBody(), {msg: "Loading..."});
Ext.ux.mask.show(); // Show the mask
// All components are loaded eg. viewport, tabpanel, button etc...
ajax_request(); // Somewhere between the code ajax request is called
// All components are loaded eg. viewport, tabpanel, button etc...
function ajax_request() {
// Other processing
Ext.ux.mask.hide(); // Hide the mask
}
});
The problem is the ajax request is taking much time now so i want to change the working something as follows:
Ext.onReady(function(){
Ext.ux.mask = new Ext.LoadMask(Ext.getBody(), {msg: "Loading..."});
Ext.ux.mask.show(); // Show the mask
// All components are loaded eg. viewport, tabpanel, button etc...
ajax_request(); // Somewhere between the code ajax request is called
// All components are loaded eg. viewport, tabpanel, button etc...
function ajax_request() {
// Other processing
//Ext.ux.mask.hide(); // Hide the mask - removed
}
// I want to call this when everything is loaded on the page
function everything_loaded() {
Ext.ux.mask.hide(); // Hide the mask
}
});
Any idea on this? Thanks a lot for help.
What ExtJs version are you referring to? 3.x or 4.x?
If 4.x, consider using/following the MVC Application Architecture guidelines. In that case, you want to override Ext.application.launch as described in MVC Application Architecture or Ext.app.Application
If 3.x, I guess Ext.onReady() is the best they have.
UPDATE
Based on your updated question, this is what you are looking for -
Ext.onReady(function(){
Ext.Ajax.on('beforerequest', showSpinner, this);
Ext.Ajax.on('requestcomplete', hideSpinner, this);
Ext.Ajax.on('requestexception', hideSpinner, this);
...
}); //end of onReady
showSpinner = function(){
//setup and show mask
}
hideSpinner = function(){
//hide mask
}
Reference - Ext.Ajax
base on your update.... i got conclusion that you are using Ext version 3.x.x
When I start the application it displays "loading" mask. Then an ajax request is fired and when it is completed, "loading" mask is removed
how did you call the ajax ?? why don't you hide the mask in ajax callback ?
Ext.Ajax.request({
url : "blabla",
method : "GET",
callback : function(){
Ext.ux.mask.hide();
}
});
or, mybe you want to try this one (this is what i used to show preload)
Try the afterlayout event and specify a method to execute when it's trigered
Thanks to amol and Warung Nasi 49. Although I couldn't find the best way, I manage to get almost expected result:
Ext.onReady(function(){
Ext.ux.mask = new Ext.LoadMask(Ext.getBody(), {msg: "Loading..."});
Ext.ux.mask.show(); // Show the mask
// All components are loaded eg. viewport, tabpanel, button etc...
setTimeout(function(){
Ext.ux.mask.hide();
}, 2000);
});

Resources