I'm building my first Backbone Marionette application, but I'm confused how to add reusable UI to my view templates, where those UI elements have JavaScript interaction.
I have built a number of UI elements like the input element shown below. This input element can be interacted with via JavaScript, for example by clicking the up/down arrows to change the input's value.
These UI elements should be reused again and again in multiple views, and there can be many instances of these UI elements contained within any given view. A mockup for one such view, containing several UI elements, is shown below.
A model for this view might look like this, and I would like to have the JavaScript interaction of my UI elements interacting with this view's model. In other words, the JavaScript interaction on a UI element will have to be able to pass an event to the model of the view inside which the UI element is shown.
var fontStyles = Backbone.Model.extend({
defaults: {
fontFamily: "Helvetica Neue",
fontWeight: "Regular",
color: "rbg(1,197,255)"
...
}
});
My Question
For a properly structured Backbone Marionette application, where would I define these reusable UI elements and their JavaScript interaction methods, in such a way that I can reuse them throughout all of my views/modules?
As another concern, will it be possible to write the HTML for these UI elements once, in a template file, and then reuse that single UI template file again and again in the underscore templates of my views? Or will I have to repeat the HTML for my UI elements in the template of every view?
Thank you for any help, and if my question is unclear please let me know.
You should create this elements as Marionette.ItemView's extensions
Each item view should be created and placed into region inside layout you want to use them
And of course, since it is ItemView it contains template:some_template,
Or Marionette.Layout extensions if they by itself also contain regions
So, as for your pictures
Small picture is ItemView
Big picture is Layout, which contains number of regions, each region contain widget, which is ItemView.
Layout receives model:some_model on initialization (Layout is extension of ItemView)
Related
Does backbone.js inherently have a way for me to detect and react to a views 'on show' and 'on hide'?
Or do I need to manually implement this using JQuery?
"essentially when a view (a page) is rendered" this is not a built in feature of backbone. You are the one defining a render method, (if you even have one, backbone doesn't have a rule to have one) or whatever way in which your view renders, so backbone can't provide such event because it doesn't know how you render things.
So if you are using pure backbone you'll have to implement it according to how you render your views.
If you use something built on top of backbone like Marionette.js, then it has set rules about how view's are rendered, hence it can and does provide events as well as call backs such as onRender, onBeforeRender.
I have a list of elements of different types. Each has a toggle which toggles their visibility. Now there are two ways to hide an element either detach it from DOM or set the visibility to hidden.
As I understand Angular still updates hidden elements so this may impact the performance. Is this true? With jQuery one can detach the element from DOM and then attach it again when it needs to be visible. But is this approach even a good practice in Angular?
From reading Angular documentation and its API it gave me an impression that Angular prefers that all templates/HTML are declared at the start and their content is dynamically changed with controllers. So if you want to add/remove elements you'd use an ng-repeat directive and then by removing elements from an array in the scope you can add/remove elements from the template. This works well with primitive elements of the same type. However, how does this work if you have a list of elements of different type?
Edited:
http://jsfiddle.net/k26bA
An example here would be a list of tools which can be made available with a checkbox. In the example the first approach has a static list of elements which can not be dynamically changed. Which means you need to know in advance which tools will be available.
The second approach has a list in the controller to which you add and remove tools and in the template use ng-repeat to iterate over that list and create the tools. However, I'm stuck here as a tool can be a button, a text field, checkbox or even a complex div.
I find it a little hard to have a model first here because this is just a part that hides and shows available controls as opposed to displaying a domain model.
A good example of what I'm thinking would be Google Maps where you can hide or minimise various controls on the map.
You probably need to familiarize yourself with the ng-switch directive. The inactive items in an ng-switch are entirely unhooked from the DOM, as opposed to an ng-hide or ng-show, which simply set the CSS styles to show or hide.
I am developing my client-side app with YUI3's APP Framework. I am having the following problem: I want to be able to have a few views (let's call them widgets) that are going to stay in the same place on page but under App's container Node, so that events can be registered within App's logic. For example I want a left menu which will have dynamic content (user's navigation panel).
This can be done by creating the menu as a subview, but navigating to another page will result in a page transition and thus, the menu will be included in page transition. I want this subview to be a shared view within many other pages(where page is formed from multiple subviews) but excluded from app's navigation behavior and rendered only once(and updated via custom events).
Does anyone with more experience using YUI App Framework knows hot can I tackle this problem? Thanks.
Yes it can be done. After a closer look on YUI's APP Framework API I found that there are 2 separate properties: container and viewContainer. The former is the node in which the app will reside and the later one is used for dynamically changing the active view on the page. Having this 2 separate properties you have the power to add watever content you want in App besides the pages (which are going to change based on events && routes).
So to conclude you can have a div element which is going to be app's container. Within this element you can write whatever html you want. You can also have another View class here which is going to change based on events(and YUI's custom events are very powerfull). And besides all this "static" html you must have another div(or of course, another html element) which is going to be the active view's container(that'll change based on events or in majority of cases, based on page's URL).
I have the basic scenario on a Dojo 1.9 + Dijit web application:
Request JSON data over the network
On the the successful reply I parse the JSON data and save to the application model
The UI watches the model and when there's data, it creates new Custom dijit/_WidgetBase instances to show the data.
Every Custom Dijit Widget is inserted to a dijit/layout/LayoutContainer via myLayoutContainer.addChild(customWidget);
Everything works fine but I would like to improve the rendering performance.
I noticed that dijit/layout/LayoutContainer is a dijit/_Container and has its own addChild() which uses dojo/dom-construct.place() which changes the DOM directly.
So I guess I could save some milliseconds if I add all my customWidget instances to a Document Fragment and then add it to the LayoutContainer with just one call to addChild().
But dijit/_Container.addChild requires a widget of type dijit/_WidgetBase so the Document Fragment approach wouldn't work.
How could I achieve my goal?
You could create a single "container" widget which contains all the logic to create the child widgets and attach it to itself. Then only add the single "parent" widget to the LayoutContainer. If you wanted to do even less you could just use a ContentPane as the "container" widget.
var contentPane = new ContentPane();
//multiple times
contentPane.addChild(...)
/layoutContainer in the page flow
layoutContainer.addChild(contentPane);
I can't comment as to how this would change performance though.
In my mobile website, I dynamically create a form in javascript, so I need the 'reload' the page to get the jQuery Mobile style.
For a listview, we can simply call $("#mylistview").listview("refresh") but there is no such feature for form.
I know that we can call "refresh" one each element of the form, but by doing this, the style is not correctly applied. Indeed, all my checkbox get separated, they don't appears in one "inset"
I there any workaround ?
Docs in the release notes:
http://jquerymobile.com/blog/2011/08/03/jquery-mobile-beta-2-released/
Example:
$('#nameOfPage').trigger('create');
Quote:
New “create” event: Easily enhance all widgets at once
While the page plugin no longer calls each plugin specifically, it
does dispatch a “pagecreate” event, which most widgets use to
auto-initialize themselves. As long as a widget plugin script is
referenced, it will automatically enhance any instances of the widgets
it finds on the page, just like before. For example, if the selectmenu
plugin is loaded, it will enhance any selects it finds within a newly
created page.
This structure now allows us to add a new create event that can be
triggered on any element, saving you the task of manually initializing
each plugin contained in that element. Until now, if a developer
loaded in content via Ajax or dynamically generated markup, they
needed to manually initialize all contained plugins (listview button,
select, etc.) to enhance the widgets in the markup.
Now, our handy create event will initialize all the necessary plugins
within that markup, just like how the page creation enhancement
process works. If you were to use Ajax to load in a block of HTML
markup (say a login form), you can trigger create to automatically
transform all the widgets it contains (inputs and buttons in this
case) into the enhanced versions. The code for this scenario would be:
$( ...new markup that contains widgets... ).appendTo( ".ui-page"
).trigger( "create" );
Create vs. refresh: An important distinction
Note that there is an important difference between the create event
and refresh method that some widgets have. The create event is suited
for enhancing raw markup that contains one or more widgets. The
refresh method that some widgets have should be used on existing
(already enhanced) widgets that have been manipulated programmatically
and need the UI be updated to match.
For example, if you had a page where you dynamically appended a new
unordered list with data-role=listview attribute after page creation,
triggering create on a parent element of that list would transform it
into a listview styled widget. If more list items were then
programmatically added, calling the listview’s refresh method would
update just those new list items to the enhanced state and leave the
existing list items untouched.