Conditionally render .hbs templates emberjs - html

EDIT:
I would like to conditionally display templates inside of a larger template as long as the presence of the larger template is True.
in sidebar.hbs
<div id="sidebar-wrapper" class="super-super-float-right-col">
<div id="sidebar-wrapper" class="super-float-right-col">
<div id="sidebar-wrapper" class="float-right-col">
{{#if permit.id}}
{{render 'applicant'}}
{{render 'location'}}
{{else}}
<h2>Nope!</h2>
{{/if}}
</div>
</div>
</div>
In application.hbs I call the sidebar and the outlet
{{render sidebar}}
{{outlet}}
So technically the sidebar is currently unrelated to the results of the {{outlet}}.
I want to connect the the results of the {{outlet}} with which templates are rendered in sidebar.hbs.
Right now I'm getting "Nope!"
EDIT: I was able to use {{#if this.id}} to make the conditions on the permit.hbs page true. Now I'm trying to figure out how to apply that same logic for rendering
Much love,
Ian

If you're in the permit template there is no point in checking if you're in the template. That's analogous to saying if true, because the only reason that code would be executing would be because it's there executing it.
If that wasn't exactly what you meant update your question.
If you want something in your template to change based on the route, the application controller has a property called currentPath which has the current application path, you can watch it and create computed properties that change based on the current path.
http://emberjs.jsbin.com/iCIkEsib/2/edit

Related

Is it possible to make a list within a list in 2sxc?

DNN 9.3.2 / 2sxc 10.25.2
Using 2sxc Content and c# Razor templates, I'm able to create a content type with some fields and enable the list mode on the template so that I can have a list of items and manage it. This is great because it lets me have one (1) 2sxc Content module on the page and list out as much content as I need.
However, in many cases, I need a "list within a list" so that I can have a repeating list of content within a repeating list of content and manage the design through the template instead of relying on my Content Editors to write HTML. See screenshot for an example.
In this design, I have 1 module that has "List" enabled and in that module I have 3 items called "Spotlights" which are just Content items. But then in each "Spotlight", there is a list of "PRE-CONFERENCE SESSIONS" which each have a title, link, and specific style (colour) for each item. In this setup, I simply made the "PRE-CONFERENCE SESSIONS" section a DNN Editor (tinymce) and then manually edit the HTML to make the FontAwesome caret and assign a CSS class to style each accordingly (each colour is important as it indicates the type of session). This method works but is cumbersome and involves me as a developer to maintain the list as the Content Editors don't know HTML.
I know that I can break this 1 module apart into 3 modules where each Spotlight is the Header content, and then the PRE-CONFERENCE SESSIONS links are the content item, but I was hoping to keep everything contained in 1 module for ease of maintenance. I also run into other scenarios in design where a sort of "sub" (or nested) list content would be really useful.
Is it possible to do this in 2sxc? Or is there a better way of achieving this?
I've done something similar to this where I created an Bootstrap Accordion and then also had a nested Bootstrap Accordion within that. Here's an example, maybe it'll help. https://www.crawfordinsurancegroup.com/commercial-insurance expand the Target Markets Accordion and you'll see a nested one within it.
I used the concept of Content-Blocks for this. In the main Accordion, I added another field called AccordionItem and made it an Entity Type and the Input Type as ContentBlocks. This give you the ability to select another 2sxc entity within your content,
https://www.screencast.com/t/iwCn2zmH8H
In your template, you can add a foreach to loop through the content items and render them
#foreach(var cb in AsDynamic(Content.AccordionItem)){
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<a role="button" data-toggle="collapse" data-parent="#accordion-#(Dnn.Module.ModuleID)" href="#collapse-#cb.EntityId" aria-expanded="true" aria-controls="collapseOne">
<strong>#cb.Title</strong>
</a>
<div class="panel-title"></div>
</div>
<div id="collapse-#cb.EntityId" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
#Html.Raw(cb.Content)
</div>
</div>
</div>
}
So in my example, I'm creating new Bootstrap accordions. You can reference the fields that are part of the nested entity (cb in my case) and output them in the template as you need them. Hope this helps.
Just as an added info: 2sxc 11.0 enhances lists-in-lists, so that the edit-toolbar of items-in-property-lists actually also get buttons like move-up/move-down etc.
enjoy ;)

Get recursive nested template call to work in Angular 2?

I hope the title isn't misleading too much as I have no idea how else to call it, but here's the problem:
I am developing an app with Angular 2 and use the nested templates (hope that's the right name for them) in several instances.
Now the issue I have is that my app consists of several "widgets" which can contain other widgets. This can create a sort of circle in the template calls.
Example:
home.html:
<div> some html stuff </div>
<widget1 *ng-for="#widget of widgetList" [widget]="widget"></widget1>
widget1.html:
<div> some html stuff unique to widget1 </div>
<div *ng-if="widget.widgetSubList">
<div *ng-for="#widget of widget.widgetSubList">
<div [ng-switch]="widget.type">
<p *ng-switch-when="2"><widget2 [widget]="widget"></></widget2></p>
<p *ng-switch-when="3"><widget3 [widget]="widget"></></widget3></p>
</div>
</div>
</div>
widget2.html
<div> some html stuff unique to widget2 </div>
<div *ng-if="widget.widgetSubList">
<div *ng-for="#widget of widget.widgetSubList">
<div [ng-switch]="widget.type">
<p *ng-switch-when="1"><widget1 [widget]="widget"></></widget1></p>
<p *ng-switch-when="3"><widget3 [widget]="widget"></></widget3></p>
</div>
</div>
</div>
widgetSubList is a property of the widget that is filled if it has sub-widgets, the ng-if does work in this case and doesn't crash the code if there are no sub-widgets.
That's the point where the whole thing crashes since it creates the mentioned "circle" of widgets containing widgets that have been in the above part of the tree already since widget1 can call widget2 which can call widget1 again.
I can't change that structure since it's predetermined by the API I use in this case.
So now the question: Is there a way to have this work?
Since all widgets require different implementations, I can't really work around it without creating one giant html file filled with ng-ifs, which I would like to avoid.
PS: I edited the example a bit further to represent the code better.
the #Input part is present in the .ts files.
Right now, I only read out one additional level of sub-widgets from the API for test purposes.
What is a bit strange is that you don't have a loop of widgets within the widget1.html and widget2.html files. With your implement, you always remain on the same widget metadata, so it's normal that you have an infinite loop...
As a matter of fact, you need to have a recursive structure that would allow to define the structure of your component:
widgetList
widget
children
widget
children
widget
children
widget
children
widget
children
(...)
So when the current widget won't have children, the recursive loop will end.
So I would refactor your templates like this (for example for widget1.html):
<div> some html stuff unique to widget1 </div>
<div *ng-for="#subWidget of widget.children">
<div [ng-switch]="subWidget.type">
<p *ng-switch-when="2"><widget2 [widget]="subWidget"></widget2></p>
<p *ng-switch-when="3"><widget3 [widget]="subWidget"></widget3</p>
</div>
</div>
Each widget would have an input corresponding to the widget metadata:
#Component({
selector: 'widget1',
(...)
})
export class Widget1Component {
#Input()
widget: any;
}

Polymer Scaffolding : Setting Title per page : Best approach

Our team is building our first polymer all in one page app and we kind of have to reverse engineer a neglected component of the project. We need to set the title for the title bar in the core-scaffolding. This is easy on simple pages by using JS, however some pages have conditional templates that show content and each require their own titles.
eg
<core-scaffolding>
<div id="title">Dynamic Title goes here</div>
<core-animated-pages transitions="cross-fade">
<section>
<div cross-fade>
<my-element>
<template if="{{condition1}}"></template>
Content 1
</template>
<template if="{{condition2}}"></template>
Content 2
</template>
<template if="{{condition3}}"></template>
Content 3
</template>
</my-element>
</div>
</section>
<section>
<div cross-fade></div>
</section>
</core-animated-pages>
I was going to add an attribute on the template elements to be able to pass a title value, however I don't know how to use JS to find out which template is the one that is conditionally rendered (active). I can't seem to find any documentation on this. Also I want to build something reusable (not with IDs) that can be used globally on any page.
Can anyone provide any suggestions?
Cheers,
david
i don't think i would use conditional template for this. if that condition changes a lot the content of the template will be added and removed from the dom every time it is changed. i think it would be better to use the hidden attribute or use databinding to change the text dynamically.
hidden attribute
<span hidden?="{{!condition1}}">Content 1</span>
<span hidden?="{{!condition2}}">Content 2</span>
<span hidden?="{{!condition2}}">Content 3</span>
databinding
<span>{{content}}</span>
then you can change the databind in javascript like normal.
if (condition1) {
this.content = 'Content 1';
}

Repeated content (sub-template) in AngularJS

I have a template which contains (in part) exactly the same content repeated two or three times with minor changes to the bindings, eg:
<div class="xyz-state0" data-ng-hide="data.error || !data.states[0].name">
<div class="xyz-content">
<img data-ng-src="{{data.states[0].image}}" width="48" height="48">
<span>{{data.states[0].name}}</span>
</div>
</div>
<div class="xyz-state1" data-ng-hide="data.error || !data.states[1].name">
<div class="xyz-content">
<img data-ng-src="{{data.states[1].image}}" width="48" height="48">
<span>{{data.states[1].name}}</span>
</div>
</div>
How do I write this to avoid duplicating this HTML? This is specific to its parent view (it won't be used anywhere else) so creating a full-blown widget seems wrong.
Basically I want something similar to ngRepeat, but I can't use that for the following reasons:
I need a specific (and different) style on each parent div.
I need to render a specific number of divs (2 in this case, 3 in another) regardless of whether or not they exist in the scope (ie. data.states could only have 1 element in it, but it still needs to create both divs).
In the other case the items need to be rendered out of order (first 1, then 0, then 2).
I've managed to get a template fragment in a separate HTML file and included it with ngInclude, but I don't know how to get a single name in its new scope to refer to a specific item. My first attempt was this, which doesn't work:
<div class="xyz-state0" data-ng-include="'state.tpl.html'" data-ng-init="state=data.state[0]"></div>
<div class="xyz-state1" data-ng-include="'state.tpl.html'" data-ng-init="state=data.state[1]"></div>
I suspect I could probably do it with a custom controller, but that seems like a heavy solution too. What's the Right Way™?
This is pretty much a textbook case for a custom directive. Define a directive, and then you can do
<state ng-repeat="item in data.states" item="item">.
Alternatively, if a custom directive is too much overkill (depends on whether you'll be reusing that view component elsewhere, mainly), you could just put an ng-repeat on the entire div. The only real issue is the class="xyz-stateN" stuff, but I bet you could hoke that up with ng-class usage.
EDIT:
if you do an ng-repeat, you can just use the $index key (as long as you're always counting up from zero and the state class is the same as the index). Something like
<div ng-class="{{'xyz-state'+$index}}" ng-repeat="state in data.states" data-ng-hide="data.error || !state.name">
<div class="xyz-content">
<img data-ng-src="{{state.image}}" width="48" height="48">
<span>{{state.name}}</span>
</div>
</div>
Would probably work fine. All that said, it's almost always worth making a directive in my opinion. Code gets recycled all the time, plus you can be cautious with namespacing and modularizing if that makes you nervous.
Well, this seems to do the trick (thanks to pfooti for the hint). I'm still not entirely happy with it as the directive is registered globally, whereas I really only want it in this one place.
state.tpl.html:
<div class="xyz-content" data-ng-show="state.name">
<img data-ng-src="{{state.image}}" width="48" height="48" />
<span>{{state.name}}</span>
</div>
view.tpl.html:
<div data-xyz-state="data.states[0]" class="xyz-state0"
data-ng-hide="data.error"></div>
<div data-xyz-state="data.states[1]" class="xyz-state1"
data-ng-hide="data.error"></div>
app.js:
app.directive('xyzState', [function() {
return {
templateUrl: 'state.tpl.html',
scope: {
state: '=xyzState',
},
};
}]);
Interestingly it doesn't work if I try to declare the introducing element as <xyz-state ...> instead of <div data-xyz-state="" ...>, despite the docs saying that this ought to work too. I assume there's some sort of validation thing interfering here.
Just as an FYI, I later revisited this code and decided to do it like this instead: (I'm letting my original answer stand as that is more like what I was originally asking for, and they both seem reasonable in different cases.)
view.tpl.html
<div data-ng-repeat="state in data.states" data-ng-if="!data.error"
data-ng-class="state.class">
<div class="xyz-content" data-ng-show="state.name">
<img data-ng-src="{{state.image}}" width="48" height="48" />
<span>{{state.name}}</span>
</div>
</div>
app.js
...
while ($scope.data.states.length < 2)
$scope.data.states.push({});
$scope.data.states[0].class = 'xyz-state1';
$scope.data.states[1].class = 'xyz-state2';
...
I've done something similar for the other (3-item) case, except there as I wanted to rearrange the order of the items I added an order property for the desired order in the controller and then used data-ng-repeat="button in data.buttons|orderBy:'order'" in the view.
This does mean that a bit of view definitions (display order and CSS classes) have leaked into the controller, but I think the benefit to code clarity outweighs that.

Unable to display error message in play1.2.4 framework html

I am currently using play framework. Here I need to display error message corresponding to a text box.
Below is the structure of the code I have been using --
<div class="row-fluid widgetRow span6 ${errors.forKey('orgName') ? 'error' : ''}">
<div class="span5 dataLabel"><label class="control-label noMargin " for="orgName">
Org Name</label><span class="required" title="required"> *</span></label></div>
<div class="span7 controls"><input id="orgName" class="" name="orgName" type="text"/></div>
</div>
Now the issue that I am facing is that, infact in a conceptual manner too, is that after I am firing an ajax save on the page, there is some play validation error(validation.required(...)) checks done in the backend, but the conditional class is never getting change. In fact as per my concept I think the condition of the class must be checked during the load of the page.
I hope this makes sense.
Please help me with this, whether there is somewhere I am mistaken
I'd personally either use #{ifError 'orgName'}error#{/ifError} or #{errorClass 'orgName'/} (and edit the CSS to include .hasError).
Aside from that, are you sure you are using the right key? You could check what errors are actually there by adding this to your template to output all errors:
#{ifErrors}
<p>Error(s) found!</p>
<ul>
#{errors}
<li>[${error_index}] ${error.key}: ${error}</li>
#{/errors}
</ul>
#{/ifErrors}