Recursion in Play framework 2.5.X - recursion

I have a play template where I loop through a list of objects that have nested lists, and I'm displaying the items iteratively using nested for loops.
-skillList is a List[Skill]
-Skill is an object defined in a model
-skillObject.getChildrenList() return a list[Skill]
What I would like to do is be able to display this but using some type of recursion so that if the level of nesting of mylist changes I don't have to change the whole template. So is there any way to do this in a recursive way ?
<div class="custom-dd dd dd-nodrag" id="nestable_list_1">
<ol class="dd-list">
#for(skill <- skillList) {
<li class="dd-item">
<div class="dd-handle dd-nodrag row">
<span class="dd-nodrag" id="content_#skill.getCleanUri()"> #skill.getLabel() </span>
</div>
<ol class="dd-list">
#for((child, indexChild) <- skill.getChildrenList().zipWithIndex) {
<li class="dd-item" data-id="#indexChild">
<div class="dd-handle dd-nodrag row">
<span id="content_#child.getCleanUri()"> #child.getLabel() </span>
</div>
<ol class="dd-list">
#for((grandChild, indexGrandChild) <- child.getChildrenList().zipWithIndex) {
<li class="dd-item" data-id="#indexGrandChild">
<div class="dd-handle dd-nodrag row">
<span id="content_#grandChild.getCleanUri()"> #grandChild.getLabel() </span>
</div>
</li>
}
<div class="text-left addNew" id="meta-#index">
<span>
<button class="btn btn-icon w-xs plusBtn
btn-primary waves-effect waves-light toggleButton" data-toggle="modal"
data-target="#custom-width-modal"> <i class="fa fa-plus" aria-hidden="true"></i>
</button>
</span>
</div>
#(index = index + 1)
</ol>
</li>
}
</ol>
</li>
}
</ol>
Thanks in advance for any answer.

You can create a separate template that takes List[Skill] as argument and renders SkillObjects in provided list and children of these SkillObjects. Then use that template at first nested level in your main page template. Like following -
SkillTemplate.scala.html
#(skills: List[Skill])()
<ol class="dd-list">
#for((child, indexChild) <- skills.zipWithIndex) {
<li class="dd-item" data-id="#indexChild">
<div class="dd-handle dd-nodrag row">
<span id="content_#child.getCleanUri()"> #child.getLabel() </span>
</div>
#SkillTemplate(child.getChildrenList())
<div class="text-left addNew" id="meta-#index">
<span>
<button class="btn btn-icon w-xs plusBtn
btn-primary waves-effect waves-light toggleButton" data-toggle="modal"
data-target="#custom-width-modal"> <i class="fa fa-plus" aria-hidden="true"></i>
</button>
</span>
</div>
#(index = index + 1)
</li>
}
</ol>
I have not been able to test it

Related

Is there a way to make mat-menu-item same size as mat-button on click?

I would like to make it so that when I click the mat-button, the menu items would be the same size and push everything else down. Below are attached images of the current situation and desired.
Current closed dropdown
Current opened dropdown
Desired closed dropdown
Here is my HTML code:
<mat-footer>
<div class="footerLinks">
<span *ngFor="let footerLink of footerContent.footerLinks">
<span *ngIf="footerLink.footerDrop.length > 1 else single">
<a mat-button [matMenuTriggerFor]="subLinks" href="javascript:void(0)" title={{footerLink.subFooterTitle}}>{{footerLink.subFooterTitle}}
<mat-icon>arrow_drop_down</mat-icon>
</a>
<mat-menu #subLinks="matMenu" arrowPosition="up">
<a mat-menu-item *ngFor="let footerDrop of footerLink.footerDrop" href={{footerDrop.subLink}} target={{footerDrop.linktarget}} title={{footerDrop.footerSubTitle}}>{{footerDrop.footerSubTitle}}</a>
</mat-menu>
</span>
<ng-template #single >
<a mat-button *ngFor="let footerDrop of footerLink.footerDrop" href={{footerDrop.subLink}} target={{footerDrop.linktarget}} title={{footerDrop.footerSubTitle}}>{{footerDrop.footerSubTitle}}</a>
</ng-template>
</span>
</div>
<div class="social">
<span *ngFor="let socialLink of footerContent.socialLinks">
<a mat-flat-button class="{{socialLink.socialMediaService}}-icon" href={{socialLink.url}} title={{socialLink.socialMediaService}} target={{socialLink.linktarget}}></a>
</span>
</div>
<div class="terms">
<mat-copywrite-footer [innerHTML]="footerContent.finePrint.value"> </mat-copywrite-footer>
</div>
</mat-footer>

materialize css button for delete not working

I have the following code in my node/express file:
{{#each allimages}}
<div class="col m3 14">
<div class="card hoverable">
<div class="card-image">
<a href="/uploads/{{imageName}}" data-lightbox="mygallery" data-title="This is a test">
<img src="/uploads/{{imageName}}">
</a>
</div>
<div class="card-action2 right-align">
<form action="/user/{{id}}?_method=DELETE" method="POST">
<button type="submit" class="btn-floating btn waves-effect waves-light red">
<i class="material-icons">delete</i>
</button>
</form>
<form action="/user/{{id}}?_method=DELETE" method="POST">
<button type="submit" class="btn-floating btn waves-effect waves-light blue">
<i class="material-icons">edit</i>
</button>
</form>
</div>
</div>
</div>
{{/each}}
I can see my delete button in red but when I click on it it does not delete the file. When I am using and type is set to submit it works perfectly with my route and deletes the file. How can I use the materialize css delete style to submit my delete request form?
Thanks guys for any help!
You need to make it a button, not an anchor. You can just add the relevant class definitions to use the styles of a Materialize button:
<div class="card-action2 right-align">
<form action="/user/{{id}}?_method=DELETE" method="POST">
<button type="submit" class="btn-floating btn waves-effect waves-light red">
<i class="material-icons">delete</i>
</button>
</form>
<a href="2.html">
<i class="material-icons blue-grey-text">edit</i>
</a>
</div>

Router Link Active not working in the below scenario, is their any alternate way to activate button dynamically?

HTML code
<div class="card-header">
<h5>Refill by date</h5>
<div class="card-header-right">
<nav class="navbar bg-faded ">
<ul class="nav navbar-nav">
<li class="nav-item" routerLinkActive="active">
<button (click)="setView('branch'); getFranchiseRefillsByDateAndBranch()" class="btn btn-mini btn-bg-c-blue btn-outline-default btn-round btn-action">
<i class="icofont icofont-ui-check"> By branch</i>
</button>
</li>
<li class="nav-item" routerLinkActive="active">
<button (click)="setView('product'); getFranchiseRefillsByDateAndProduct()" class="btn btn-mini btn-bg-c-blue btn-outline-default btn-round btn-action">
<i class="icofont icofont-ui-check"> By product</i>
</button>
</li>
<li class="nav-item" routerLinkActive="active">
<button (click)="setView('list'); getFranchiseRefillsByDateAndList()" class="btn btn-mini btn-bg-c-blue btn-outline-default btn-round btn-action">
<i class="icofont icofont-ui-check"> Refill list</i>
</button>
</li>
</ul>
</nav>
</div>
</div>
part of TS code
getFranchiseRefillsByDateAndBranch() {
this.items = [];
var hrchyIds = this.jwtHelperService.getFRefillHrchyIds();
var ym = this.localStorage.retrieve('frym');
if (hrchyIds) {
this.refillService.getFranchiseRefillsByDateAndYear(hrchyIds, ym, "branch", this.page, this.rec).subscribe(val => {
this.items = val;
});
}
}
CSS code
.nav-item.active button i{
color: #3D94CD !important;
}
I am trying to change color of active button using router link active but this method does not work in this case, is their any alternate way of adding class dynamically, based on current click.
routerLinkActive works if there was a routerLink on this element.
Keep currentActiveItem variable in ts file. Set some default value say "branch"
currentActiveItem : string = "branch"
Change value of this variable in setView function.
And additionally also use ngClass as following on correspondiong li elements.
[ngClass]="{'active' : currentActiveItem == 'branch'}"
[ngClass]="{'active' : currentActiveItem == 'product'}"
[ngClass]="{'active' : currentActiveItem == 'list'}"

Align bootstrap dropdown in input-group to left (underneath the start of the input)

I have a input group (text input and button with dropdown). I am having trouble getting my dropdown to align with the text box.
<div class="row">
<div class="col-xs-6">
<div class="input-group">
<input type="text" class="form-control" />
<div class="input-group-btn">
<div class="dropdown open">
<button class="btn btn-secondary dropdown-toggle"
type="button"
id="dropdownMenuButton"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
dropdown
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
I have tried <div class="dropdown-menu dropdown-menu-left"> with no avail.
Here is a fiddle
What do I need to add to this to align my dropdown menu to the left underneath the start of the input (as if it was a typeahead)?
EDIT: within the dropdown menu is an angular directive, that's likely a relative tool
Here is the Quick Fix
Working Demo Here
HTML:
<div class="container">
<div class="row">
<div class="col-xs-6">
<div class="input-group">
<div class="testing">
<input type="text" class="form-control" />
</div>
<div class="input-group-btn">
<div class="dropdown open">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="false" aria-expanded="false">dropdown</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
.testing {
position: relative;
}
JS:
$(document).ready(function() {
dropmenuWidgetPosition();
function dropmenuWidgetPosition() {
$('#dropdownMenuButton').dropdown('toggle');
$(window).on('show.bs.dropdown', function(e) {
var dropdownMenu = $(e.target).find('.dropdown-menu');
var dropMenuDetach = dropdownMenu.detach();
// detach it and append it to the target
$(e.target).parents('.input-group').eq(0).find('.testing').append(dropMenuDetach);
// grab the new offset position
var eOffset = $(e.target).offset();
// make sure to place it where it would normally go (this
// could be
// improved)
dropdownMenu.css({
'display': 'block',
'top': eOffset.top + $(e.target).outerHeight(),
'left': 0
});
});
// and when you hide it, reattach the drop down, and hide it
// normally
$(window).on('hide.bs.dropdown', function(e) {
var dropdownMenu = $(e.target).parents().find('.dropdown-menu');
var dropMenuDetach = dropdownMenu.detach();
$(e.target).append(dropMenuDetach);
dropdownMenu.hide();
});
}
});

Set a button group's width to 100% and make buttons equal width?

I'm using Bootstrap, and I'd like to set an entire btn-group to have a width of 100% of its parent element. I'd also like the inner buttons to take equal widths. As it is, I can't achieve either.
I've made a JSFiddle here: http://jsfiddle.net/BcQZR/12/
Here is the HTML:
<div class="span8 background">
<div class="btn-group btn-block" id="colours">
<span class="btn"><input type='checkbox' name='size' value='red'/>red</span>
<span class="btn"><input type='checkbox' name='size' value='orange'/>orange</span>
<span class="btn"><input type='checkbox' name='size' value='yellow'/>yellow</span>
</div> <!-- /btn-group -->
</div>
And here is my current CSS, which doesn't work:
#colours {
width: 100%;
}
Bootstrap has the .btn-group-justified css class.
How it's structured is based on the type of tags you use.
With <a> tags
<div class="btn-group btn-group-justified" role="group" aria-label="...">
...
</div>
With <button> tags
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default">Left</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default">Middle</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default">Right</button>
</div>
</div>
There's no need for extra css the .btn-group-justified class does this.
You have to add this to the parent element and then wrap each btn element in a div with .btn-group like this
<div class="form-group">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="submit" id="like" class="btn btn-lg btn-success ">Like</button>
</div>
<div class="btn-group">
<button type="submit" id="nope" class="btn btn-lg btn-danger ">Nope</button>
</div>
</div>
</div>
BOOTSTRAP 2 (source)
The problem is that there is no width set on the buttons. Try this:
.btn {width:20%;}
EDIT:
By default the buttons take an auto width of its text length plus some padding, so I guess for your example it is probably more like 14.5% for 5 buttons (to compensate for the padding).
Note:
If you don't want to try and compensate for padding you can use box-sizing:border-box;
http://www.w3schools.com/cssref/css3_pr_box-sizing.asp
I don't like the solution of settings widths on .btn because it assumes there'll always be the same number of items in the .btn-group. This is a faulty assumption and leads to bloated, presentation-specific CSS.
A better solution is to change how .btn-group with .btn-block and child .btn(s) are display. I believe this is what you're looking for:
.btn-group.btn-block {
display: table;
}
.btn-group.btn-block > .btn {
display: table-cell;
}
Here's a fiddle: http://jsfiddle.net/DEwX8/123/
If you'd prefer to have equal-width buttons (within reason) and can support only browsers that support flexbox, try this instead:
.btn-group.btn-block {
display: flex;
}
.btn-group.btn-block > .btn {
flex: 1;
}
Here's a fiddle: http://jsfiddle.net/DEwX8/124/
For bootstrap 4 just add this class:
w-100
Bootstrap 4 removed .btn-group-justified. As a replacement you can use <div class="btn-group d-flex" role="group"></div> as a wrapper around elements with .w-100.
Try this:
<div class="btn-group d-flex" role="group>
<button type="button" class="btn btn-primary w-100">Submit</button>
<button type="button" class="btn btn-primary w-100">Cancel</button>
</div>
Angular - equal width button group
Assuming you have an array of 'things' in your scope...
Make sure the parent div has a width of 100%.
Use ng-repeat to create the buttons within the button group.
Use ng-style to calculate the width for each button.
<div class="btn-group"
style="width: 100%;">
<button ng-repeat="thing in things"
class="btn btn-default"
ng-style="{width: (100/things.length)+'%'}">
{{thing}}
</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="btn-group btn-block">
<button type="button" data-toggle="dropdown" class="btn btn-default btn-xs btn-block dropdown-toggle">Actions <span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span></button><ul role="menu" class="dropdown-menu"><li>Action one</li><li class="divider"></li><li><a href="#" >Action Two</a></li></ul></div>
Bootstrap 4
<ul class="nav nav-pills nav-fill">
<li class="nav-item">
<a class="nav-link active" href="#">Active</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Longer nav link</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
</ul>
Bootstrap 4 Solution
<div class="btn-group w-100">
<button type="button" class="btn">One</button>
<button type="button" class="btn">Two</button>
<button type="button" class="btn">Three</button>
</div>
You basically tell the btn-group container to have width 100% by adding w-100 class to it. The buttons inside will fill in the whole space automatically.

Resources