Is there a way that I can tell backbone/marionette not to automatically add a the wrapping container tag when rendering a view to a region?
For example, lets say I want to display a list of items. The way I want to do that is by having one composite view looking looks this:
<ul>
</ul>
And then a item view that looks like this:
<li><%= title %></li>
Now I can easily get the same output by changing what the tag used for the auto generated element is however the biggest reason I would not have the tag automatically generated by backbone/marionette is because I want to keep as much html in the template as possible. If for whatever reason I want to change the list to a table, if all the HTML is contained in templates, I only have to change the two template files. The other way would require me to change 2 template files and 2 javascript files (less file I have to change to make a change, the less chance for error). I just like to have that level of separation of concern.
Neither Backbone nor Marionette have built in support for this. But I imagine if you could get this behaviour with a few tweaks.
Backbone.View has a method called _ensureElement that constructs the el from tagName and className if the el is not provided.
You could override _ensureElement to render the template first an then use it's first tag name as the tagName for the view. You'd also need to override Marionette.Renderer.render to strip the template's outer tag.
There maybe a better choice of methods to override to achieve this logic. I would also advise that you provide a flag somewhere to turn this behaviour on selectively so you could mix and match as needed, which would also help in debugging.
Related
I want to display a list of events of very different types that should have different UI logic. Yes, they have common properties (like name, date/time, location etc) but also sets of custom properties that can be simple text, typeahead items, drop down lists etc. Depending on the specific event type (there will be tens of them) I need to handle user input in different ways. For example, on select a typeahead item I want to clear two other fields etc.
I'm gonna display those events using ng-repeat and dynamically load template views depending on the specific event type. These views will have proper controllers that are specific to the business object. I still haven't make it work but please advice me.
Is loading type-related views with controllers inside is a good idea
for this task?
Would directives instead of controllers be better?
Is there a way to dynamically set controller/directive name in the HTML attribute?
Any other advices?
yes
yes, use directives. If you have a base event definition, it is probably best to define an element directive for that and use attribute directives to extend/customize the functionality for different event types.
not exactly, but you can use ng-switch on your list item element.
example:
<li ng-repeat="event in events" ng-switch on="event.type">
<my-event event="event" first-type ng-switch-when="type1"></my-event>
<my-event event="event" second-type ng-switch-when="type2"></my-event>
<my-event event="event" third-type ng-switch-when="type3"></my-event>
<my-event event="event" ng-switch-default></my-event>
</li>
Use require: 'myEvent' in your extending directives to gain access to the base myEvent controller.
Demo
I am using a directive "slideable" which creates a slideout area and has a toggle. This code that was not written by me but it demonstrates a larger issue for me. When I changing views (most commonly /user/:id type), slideable is a directive used on the template. The directive searches for an element during its link function and binds a click event. The issue is that when I am changing routes and the new view ( same type but different id ) is being loaded the directive is re-binding to the old view. If I stop the browser in chrome during the link then I will see two ng-views on the dom and the issue is it binds to the one that is leaving.
I also have other issues that appear to be related to this phenomenon. Is it normal that the old view would still be on the dom while the new view is being formulated?? Why wouldnt the old-view be destroyed before the new one is rendered? How do I get around this issue in a directive like this?
Thanks.
I am looking to understand conceptually what is happening. I already modified the directive to select the latest view and to appropriately search and bind to the correct element. But I am a bit perplexed as to why there would be a state where both co-exist on the dom.
One definitive reason why the old HTML fragment is briefly present along with the new one is to support animation of transitions from the old to the new. Take a look at the ngView documentation and you'll see an example of an animated transition, and it'll be clear that this is not a bug or a design flaw.
Usually when someone has problems with binding to the right element or element's event, it's because they are selecting the element without limiting the scope of the selector to the HTML fragment being added or updated, or trying to target parts of the DOM outside of the directive. So that's the first place to check, that the directive is doing things right, but like I said we'll need code to check on that.
I have an angular multi-step form in a modal window. It has a few different views and works great but at the end of it I just want to display a tiny snippet of HTML along the lines of 'Thank you, we will be in touch shortly'
However, I thought about creating a view for this with a partial but it seems incredibly over-engineered for what it is. Is there any way in angular of just replacing the view with that sentence without creating a whole new view? This will be called from a function in the final controller
Use ng-show and ng-hide to do this in your view. Suppose if your view is no longer needed you can hide it and show the Thank you snippet at its place by using ng-show.
ng-switch is what you are looking for.
From the docs:
"The directive itself works similar to ngInclude, however, instead of
downloading template code (or loading it from the template cache),
ngSwitch simply choses one of the nested elements and makes it visible
based on which element matches the value obtained from the evaluated
expression."
http://docs.angularjs.org/api/ng.directive:ngSwitch
you can this code, if you have one area of content
<ng-view></ng-view>
good method you can find in LINK
I'm actually not sure if this is possible, but I will ask it anyway. I have a group of accordion controls, and within the content body of each I need to display a grid panel. The grid panel needs to have a click event attached to it. I have tried simply creating the grid panel and setting the html property of the accordion to it, but this produces no content.
Is there somehow I can achieve the above?
You cannot have html content (inserted by the property) along with any other content. If you add any item the html property value will not set/overriden. But for sure you can place anything you want into one accordion panel. Even a grid. But for that case, and based on the last question, I would recommend you to reference the view into the grid. You may do this simply by using a ComponentQuery
The click events can be applied by using the control function of the controller.
For your basic understanding:
In ExtJS you seldom use plain html code. In most scenarios you use any sort of component. All is nested within the items-array or dockedItem-array. Items within these arrays get also processed by the layout system.
Some Query examples applicable to the control function
In the following this refers to the controller itself.
You know the Id of the grid (normally you didn't do this). Id's are marke by a starting #
control({'#yourId': {itemclick: this.onItemclick }});
You know the xtype and that there is only one instance of this type. You can also describe a path by using spaces between the xtypes.
control({'grid': {itemclick: this.onItemclick }});
You have set a custom property to grid (you can refer any property this way). This one is fully compatible the the one above. I recommend this one in your case
control({'grid[customIdent=accordionGrid]': {itemclick: this.onItemclick }});
This are just some ways to use ComponentQueries, there are more. For a more detailed explanation you should refer the sencha API for ComponentQuery
Also note that every component implements the up() and down() methods which also support ComponentQueries.
I forgot to mention: For a control the query strictly need to return just one result (only the first one will be taken) a ComponentQuery on the other hand can return multiple results.
This is perfectly possible but the accordion's body is not the place to put that in. You'll need to add it to the items: [] array of the accodion. The body (or html) only accepts html.
Example:
http://docs.sencha.com/ext-js/4-1/#!/example/layout/accordion.html
this one has a grid within it.
I'd like to be able to generate a component from within a template. The use case for it is that when I generate a row in a DataView I'd like to be able to incorporate buttons and/or other components (maybe even a nested grid) to the rendered items.
So far everywhere I look all I see is a template calling another template. Is there a way to do what I'd like (generate component instead of just plain html) from an XTemplate?
Since an XTemplate is just used for generating markup to be inserted into the DOM, it alone is not enough to create components -- Components do have an underlying DOM element (through component.el.dom), but also exist as JavaScript objects in browser memory with other methods and properties.
It is possible to accomplish what you are asking through several different ways... you can use the XTemplate to generate the markup, and use the Component.applyTo config option to create a Component object in memory that is linked to the DOM element from your template. Of course, you will have to wait until the template is applied and then create a component with applyTo set to the correct DOM element.
You could also extend the XTemplate class to do the same thing just mentioned, but wrapped up in the applyTemplate stuff. I am pretty sure that Ext does not have a built-in way for the templates to create components -- so far they just create HTML.