I'm generating a list of views that the client should cycle through on the server. The server returns a list of something like 'App.AView', 'App.BView', 'App.CView", ..., etc. that refer to views and templates on the client.
I'd like to dynamically create these views, swap out the previous view, and include the new view. My first though was to compile a handlebars template with this dynamic view name, ala:
App.QuestionView = Em.View.extend({
template: function() {
return Ember.Handlebars.compile("{{view " + this.get("view_name') + "}}");
}
});
Which works, but seems ugly - is there a way to create a view with a string of the view name in Ember.JS and replace an existing view in a parent view with that view?
You want to look at Ember.ContainerView, which will let you programmatically manage a set of child views. Container View's documentation is excellent, check out: http://emberjs.com/api/classes/Ember.ContainerView.html
Since it sounds like you only ever want one view displayed at a time you can focus on the currentView property, which will automatically maintain your childViews array for displaying a single view.
Also here is an example: http://www.emberplay.com/#/workspace/2792969430
Related
I have navbar component which I have placed in an application.hbs so that it should be visible always.But I want to change the title of the navbar with each page I visit ( say I am on index page it should say "Home" , if I am on profile page it should say profile,etc).Right now what is happening is navbar title always remains "Home" for all the page.This is happening because the navbar gets rendered onlu during the time it loads the page in browser and after that it doesn't change according to page.
application.hbs
{{top-navbar dp_url=model.profile.dp_url first_name=model.profile.first_name title=title}}
{{outlet}}
Here the I am computing the value of title depending upon which page the user is.
application.js(controller)
if (currentPage === "" || currentPage === "#"){
currentState.set('title',"Home")
}
else if(currentPage === "Userprofile"){
console.log('myStudio');
currentState.set('title',"UserProfile");
}
In here the currentpage has the current url of app and I am comparing it and deciding the value of title for navbar.
But the top-navbar title value gets calculated only for the first time when user load the app in browser and not when I move ffrom one route to another.
I have also tried the Ember.Evented but not able to solve it.
I don't know what Ember.js and Ember-data version are you using, currentState is deprecated since 2.1, anyway looks like you're using a private method intended for Ember internals and not meant to be used in an application.
A possible (but maybe unnecessary complicated) way to accomplish what you want is:
Create a model with the information you want to mutate in the navbar (e.g. navbar-data).
In the route where the navbar is rendered, create and return a record for it using a fixed numeric ID (e.g. store.createRecord('navbar-data', { id: 1, title: "index" })).
Pass the created record to the component (instead of just a string).
Whenever you want to change, peek the record with store.peekRecord('navbar-data', 1) and change the value you want to change in the navbar.
Of course, the record you use for that must not be saved with record.save().
I'm beginning to use Marionette within an existing backbone application. I've got some HTML which I want to append into a region. In pure backbone, I could just do this.$el.append(html_code) and that was all. As far as I can see, marionette regions allow only to operate on views (which have to implement the render method). Calling append on marionette region throws 'undefined method' errors.
Is it possible to attach plain HTML to a marionette region?
No, it's not possible to inject plain html into a Marionette.Region.
Theoretically you could access a regions DOM element with someRegion.el or someRegion.getElement(), but this must be done after rendering (which at least isn't possible inside a Marionette.View with standard behaviour).
But you can achieve the desired result by using a specially crafted Marionette.ItemView:
#someRegion.show(new Marionette.ItemView({template: '<h1>gach</h1>'}));
You maybe also should have a look at Marionette.Renderer .
a Marionette ItemView will look for a template and will call render on that template, so when you show the view in the region the html will be displayed just fine with out the need of you defining a render method.
MyImtemView = Backbone.Marionete.ItemView.extend({
template : "#myTemplate"
});
var myItemView = new MyItemView();
myLayout.aregion.show(myItemview);
this should work if you save your html in a template like this
`<script id="myTemplate" type="text/template">
<div><p>your html<p>
</div>
`
EDIT
you can also declare a render function in your view in case you need to generate and modify your html like this.
MyImtemView = Backbone.Marionete.ItemView.extend({
template : "#myTemplate",
render : function (){
this.$el.append(HMTL); //so here you work your html as you need
}
});
var myItemView = new MyItemView();
myLayout.aregion.show(myItemview); //the render function of your view will be called here
I ran into the same problem and tried the answers explained here, but I'm also using require.js and kept getting an error for the #my_view template not being found. If anyone can clarify where does Marionette look up the templates by default, that would be great.
Instead, I solved it by using the text.js plugin for underscore.js. This way you actually can use a plain html file as the template, without the need for nesting it in a script tag. Here's how I did it.
define(['backbone', 'underscore', 'marionette', 'text!tmpl/my_view.html'], function(Backbone, _, Marionette, view_t){
var MyView = Backbone.Marionette.ItemView.extend({
template : function(serialized_model) {
//define your parameters here
param1 = erialized_model.param1;
return _.template(view_t)({
param1: param1
});
}
});
return MyView;
});
I placed the text.js plugin in the same lib directory as all my other js libraries and my main.js for require declares the path to the templates as
'tmpl': '../../templates',
My project structure looks like this
root
index.html
js
main.js
app
App.js
views
MyView.js
lib
require.js
text.js
backbone.js
underscore.js
jquery.js
backbone.marionette.js
templates
my_view.html
My template 'my_view.html' simply looks like this.
<h1>THIS IS FROM THE TEMPLATE!!!</h1>
Worked perfectly. I hope you find it useful.
Using a view
var myHtml = '<h1>Hello world!</h1>';
var myView = new Marionette.ItemView({template: _.constant(myHtml)});
myRegion.show(myView);
Marionette.Renderer.render takes either a function or the name of a template (source code). _.constant creates a function that returns the passed-in parameter.
Attaching HTML
Alternately, the docs for Marionette.Region mention overriding the attachHtml method, see Set How View's el Is Attached.
I have a list component which is filled out using a data store(data loaded from server as json). A part of data from data store is displayed as list items, and i need some kind of a "+" button to the left of it to expand a list item(and "-" to collapse) to reveal(/hide) the remaining info. I could simply put some javascript to itemTpl tag but i've no idea how to make smooth transitions this way. Maybe am missing some standard settings for a list component, but i can't find any info. Any help appreciated.
There is no standard settings to do this functionality. But this is possible to achieve. You can have your item template as something like this:
itemTpl: '<div class="plus"></div><div class="title">{title}</div><div class="hidden">{mydetails}</div>'
Initially, the details is hidden. You need to handle the animation when your taps the list item. So, in your event you will have to do:
itemtap: function(view,index,htmlElement,e,opts) {
// change the div plus to minu..
// Get hold of the div with details class and animate
var el = htmlElement.select('div[class=hidden]');
el.toggleCls('hidden'); //remove the hidden class if available..
el.show(true); // show with animation
}
The object is obtained from select() method is Ext.dom.CompositeElementLite .. Refer this class for more methods. You can call the Ext.Anim from this object as well..
To animate you can use the Ext.Anim class. Once you have the html element of you 'details' div, you can:
Ext.Anim.run(detailsDiv,'slide',{
out:false,
from: 'hiddenCSS',
to: 'visibleCSS'
});
Refer to Anim class for more setting that might be needed to have your desired effect. Also note that you will have to track the previously clicked (expanded) list items.
Smartgrid component in web2py is very powerful. I wonder if it is possible to add any additional markup into the View/Edit pages of the smartgrid.
Normall, in web2py we need to create a view html file corresponding to a function in the controller. The problem with smartgrid is that the controller functions are automatically defined by the component.
For example, clicking the View button in a smartgrid goes to the following url:
default/index/dataset/view/dataset/1
Now, my question is if I can create a custom view html file for this page that can contain things other than smartgrid?
The smartgrid component is not automatically defining controller functions. Rather, the links for view, edit, etc. are simply passing additional arguments to the same function where the smartgrid is defined (e.g., in the above URL, dataset/view/dataset/1 are all arguments to the index function, which presumably is where your smartgrid is defined).
You have at least two options. First, you could add conditional logic to the index.html view, such as:
{{if 'view' in request.args:}}
[special code for viewing a record]
{{else:}}
[regular grid view code]
{{pass}}
Alternatively, you could specify a different view from within the controller function, such as:
def index():
if 'view' in request.args:
response.view = 'default/view_record.html'
[rest of index code]
I am trying to use flowplayer's overlay to load an external page that has a django form built in.
However the overlay loads the page but the submit button simply refreshes the page.
How do i actually submit the values entered in the form?
<script src="http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js"></script>
<script>
$(function() {
// if the function argument is given to overlay,
// it is assumed to be the onBeforeLoad event listener
$("a[rel]").overlay({
mask: {
color: '#ebecff',
loadSpeed: 200,
opacity: 0.9
},
effect: 'apple',
closeOnClick: false,
onBeforeLoad: function() {
// grab wrapper element inside content
var wrap = this.getOverlay().find(".contentWrap");
// load the page specified in the trigger
wrap.load(this.getTrigger().attr("href"));
}
});
});
</script>
<div class="bananas">launch</div>
my view boom has a model form.
Without seeing the actual view code, it's hard to give a helpful answer. In the future, please be sure to do so...
If you don't have the overlay programmed to redirect to the page, then submitting it to that same url might process/save the data without you noticing. Is the data being saved, or does absolutely nothing happen when you click 'submit'?
Generally, this is how it works: you need to be posting to a url, defined in urls.py, that points to a view function in your views.py. (These names are merely convention, and can be called whatever you like) You mentioned that you have a view named 'boom': is it defined in your urls.py like this?
url(r'^path/to/boom/$', 'model.views.boom',),
Check that this is defined and that your form is posting to it.
The view must then contain logic to process the request and return a response. Posting to that url will transfer a cleaned_data dictionary of form variables that can be accessed over the field names defined in the form. It looks like this: x = form.cleaned_data[x]. Check the form for its validity with form.is_valid(), and then do your processing. This can involve saving objects, running arbitrary code, whatever you wish.
To find out more, be sure to read the excellent documentation.