Using handlebars to iterate over a complex object - javascript

I have a special array how can I itereate over it ?
It looks like:
{
"0.1.0": {
"pictures": {
"list": ""
},
"show": true,
"implemented ": false,
"percentageDoneVersion": 100,
"description": "Programmierung ...",
"tasks": {
"1":{
"percentageDone":10,
"description":"Text1..."
},
"2":{
"percentageDone":70,
"description":"Text2..."
},
"3":{
"percentageDone":10,
"description":"Text3..."
}
}
}
}
I tried different things, but they did not work out...
Thank you.

I am not fully clear on the requirements but as per provided information, looks like you are looking from something link this:
<script id="template" type="text/x-template">
<div class="row" style="">
<hr>
<div class="col-xs-12 col-lg-12">
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title"><a data-toggle="collapse" data-parent="#versionHeading{{#index}}" href="#versionHeading{{#index}}">{{{body.project.versionHeading}}}</a></h4>
</div>
<div id="versionHeading{{#index}}" class="panel-collapse collapse in">
<div class="panel-body">
<p>{{{body.project.versionIntro}}}:</p>
{{#each body.project.versionContent}}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title"><a data-toggle="collapse" data-parent="#mainVersion{{#index}}" href="#mainVersion{{#index}}">Version {{#key}}</a></h4>
</div>
<div id="mainVersion{{#index}}" class="panel-collapse collapse in">
<div class="panel-body">
<p>{{{this.description}}}</p>
<ul>
{{#each this.tasks}}
<li>{{#key}}.) {{{this.description}}} (progress ({{this.percentageDone}}% done)</li>
{{/each}}
</ul>
</div>
</div>
</div>
{{/each}}
</div>
</div>
</div>
</div>
</div>
</div>
</script>
Assuming that your provided json data is wrapped inside a body and project structure i.e.
{
"body": {
"project": {
"versionContent": {
....
}
}
}
}
Here is a working jsFiddle from your data and html. You can improve this as required. Version and Tasks both can grow dynamically. I recommend you to go through this simple Handlebars tutorial.

Related

Show/Hide Multiple Div using multiple checkbox when checked

I am trying to show/hide multiple div's using multiple checkboxes.
i.e. if a checkbox is checked it must target div using id or name and the div contents should be hidden.
Tried the following work but unable to achieve the required goal
<form id="varsection">
<div class="panel box box-primary">
<div id="controlledvariables" class="panel-collapse collapse" aria-expanded="false" style="height: 0px;">
<div class="box-body">
<div class="col-md-9">
<div class="row secrow">Wave</div>
<div class="row secrow">Gender</div>
</div>
<div class="col-md-1">
//if input name="Wave[]" is selected then
<div class="row secrow" style="text-align: center;">
<input type="checkbox" name="Wave[]" value="top">
</div>
<div class="row secrow" style="text-align: center;">
<input type="checkbox" name="Gender[]" value="top">
</div>
</div>
</div>
</div>
</div>
</form>
<form id="filters">
<div>
//show this div
<div class="panel box box-primary">
<div class="box-header with-border">
<h4 class="box-title">
<a data-toggle="collapse" data-parent="#accordion" href="#Wave" aria-expanded="false" class="collapsed">
Wave
</a>
</h4>
</div>
<div id="Wave" class="panel-collapse collapse" aria-expanded="false" style="height: 0px;">
<div class="box-body">
<div class="col-md-8">
</div>
<div class="col-md-4">
//or this one
<ul>
<li><input type="checkbox" name="Wave_fiters[]" value="1">Wave-1</li>
<li><input type="checkbox" name="Wave_fiters[]" value="2">Wave-2</li>
</ul>
</div>
</div>
</div>
</div>
[Other multiple div's]
</div>
</form>
jQuery
jQuery(function() {
var checks = $("[name='_Wave[]']");
checks.click(function() {
if (checks.filter(':checked').length == checks.length) {
$("[name='_Wave[]']").show();
} else {
$("[name='_Wave[]']").hide();
}
}).triggerHandler('click')
})
you have 2 problems with this code:
first the jquery selector is wrong it should be like this:
var checks = $("[name='Wave[]']");
without _
second you need to give the div you want to toggle a unique id or a class name
so your code should be like this
jQuery(function () {
var checks = $("[name='Wave[]']");
checks.click(function () {
if (checks.filter(':checked').length == checks.length) {
$(".waveDiv").show();
} else {
$(".waveDiv").hide();
}
}).triggerHandler('click')
})
and this is your input:
<input type="checkbox" name="Wave[]" value="top">
and your div which will be toggled:
<div class="waveDiv panel box box-primary">

Nested v-for in vuejs for accordian data

I am building a small application on VueJS 2.5.17 where I am having nested accordion data which I need to display through click events, I have a hierarchy of Root -> Roles -> Specialisation -> withRoles .... and so on. I am trying to get child elements on every click of their respective parents.
Following is my HTML Code:
<div class="panel-group" id="accordion1" v-for="items in accordianData">
<div class="panel my-panel-warning">
<div class="panel-heading">
<h4 class="panel-title">
<a style="color: #000; font-size: 14px" data-toggle="collapse" data-parent="#accordion1" :href="'#'+items.id">DOCUMENTED RELATIONSHIPS ({{count}})</a>
</h4>
</div>
<div :id="items.id" class="panel-collapse collapse">
<div class="my-panel-body">
<div class="my-panel-body">
<div class="panel-group" :id="items.id" >
<div class="panel my-panel-warning" v-for="child1 in roles">
<div class="panel-heading">
<a data-toggle="collapse" :data-parent="'#'+items.id" :id="'child'+child1.id" :href="'#role'+child1.id" #click="getSpecialisation(child1.id, child1.name)">{{child1.name+" (0)"}}</a>
</div>
<div class="my-panel-body">
<div :id="'role'+child1.id" class="panel-collapse collapse">
<div class="panel my-panel-warning" v-if="child1.id === child2.parent_id" v-for="child2 in specialisations[child1.name]">
<div class="panel-heading">
<a data-toggle="collapse" :data-parent="'#role'+child1.id" :id="'child2'+child2.id" :href="'#spec'+child2.id" #click="getWithRoles(child2.id)">{{child2.name+" (0)"}}</a>
</div>
<div class="my-panel-body">
<div :id="'spec'+child2.id" class="panel-collapse collapse">
<div class="my-panel-body">
.
.
.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
And calling following function in my methods:
getSpecialisation(id, name) {
axios.get('specialisations?company_id='+this.company_id+'&role_id='+id, {headers: getHeader()}).then(response => {
if(response.status === 200)
{
this.specialisations[name] = response.data.specialisations
}
})
},
But some how I am unable to display the data. Previously I tried v-for="child2 in specialisations" and in response I did this.specialisations = response.data.specialisations I was getting all similar child element for all parents I know this is wrong but just wanted to inform that I was getting data and my accordion was displaying child elements, but once I did according to above method getSpecialisation mentioned, I am unable to display the data.
I can see my data in vue console:
Suggest me a better way for this.
Thanks
Instead of this.specialisations[name] = response.data.specialisations try:
Vue.set(this.specialisations, name, response.data.specialisations)
That should trigger Vue's change-detection.
Ps. When you see lots of nesting, this might be good time to split a big component up into smaller components.

Close every other panel apart from the one being opened using Angular 2

I'm trying to click on a panel and open it's body attached to it. However, I'm opening all the bodies.
I've got the following HTML code:
<div id="contractModifyPanel" class="container body-content">
<div class="clearfix">
<h2>
{{ title }}
<span id="role" style="float: right;">
<button id="btnExportRateGridContract" type="button" class="btn btn-default btn-sm" onclick="">
<span class="glyphicon glyphicon-export"></span> Export Rate Grid
</button>
</span>
</h2>
</div>
<h4>{{ contractInstructions }}</h4>
<div class="panel panel-default" (click)="openBodyPanel()">
<div class="panel-heading warnOnExit">
<span class="glyphicon glyphicon-chevron-{{arrowDirection}} chevronIcon"></span>
<h3 class="panel-title">Contract Information</h3>
</div>
<div class="panel-body" *ngIf="showBody">
</div>
</div>
<div class="panel panel-default" (click)="openBodyPanel()">
<div class="panel-heading">
<span class="glyphicon glyphicon-chevron-{{arrowDirection}} chevronIcon"></span>
<h3 class="panel-title">Firm Fees</h3>
</div>
<div class="panel-body" *ngIf="showBody">
</div>
</div>
<div class="panel panel-default" (click)="openBodyPanel()">
<div class="panel-heading">
<span class="glyphicon glyphicon-chevron-{{arrowDirection}} chevronIcon"></span>
<h3 class="panel-title">Product Selection</h3>
</div>
<div class="panel-body" *ngIf="showBody">
</div>
</div>
<div class="panel panel-default" (click)="openBodyPanel()">
<div class="panel-heading">
<span class="glyphicon glyphicon-chevron-{{arrowDirection}} chevronIcon"></span>
<h3 class="panel-title">Product Level Fees</h3>
</div>
<div class="panel-body" *ngIf="showBody">
</div>
</div>
<div class="panel panel-default" (click)="openBodyPanel()">
<div class="panel-heading">
<span class="glyphicon glyphicon-chevron-{{arrowDirection}} chevronIcon"></span>
<h3 class="panel-title">Footnotes and Exceptions</h3>
</div>
<div class="panel-body" *ngIf="showBody">
</div>
</div>
</div>
And my .ts file looks like:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'modify-contract',
templateUrl: './modify-contract.html',
styleUrls: ['./modify-contract.css']
})
export class ModifyContractComponent implements OnInit {
title: string = 'Modify Contract';
contractInstructions: string = 'Complete the following steps to create a
contract, specify firm and program fees, and assign Product(s)';
arrowDirection: string = 'right';
showBody: boolean;
openPanel: boolean;
closedPanels: boolean;
constructor() {
this.showBody = false;
}
openBodyPanel() {
this.showBody = !this.showBody;
this.arrowDirection = (this.showBody ? 'down': 'right');
}
ngOnInit() { }
}
Every time I choose to click one panel, all of the bodies underneath the specific div opens up. How would I go about opening an individual panel without creating unique identifiers? In case I end up having to create a 100 panels, I don't want to label 100 unique identifiers.
Refactor that logic into a component (which will also help clear up all that redundant copy & paste HTML), the controller instances will each have their own showBody property, independent of the other instances.
In terms of closing other panels automatically, there are multiple options:
You can use a parent component/directive that adds all child components to a list. A click on a panel could be handled by this parent which closes all its other panels and opens the one that was clicked on.
Alternatively you could use some directive with a key value which has some internal dictionary keeping track of all panels with the same key. It could then also manage this logic. You would of course have to define this kind of directive on all panels, with the same key.

javascript doesn't work in all elements of foreach MVC

i build a code for comments and replies of them.. i use a #foreachto show all elements in ViewBag which have a list of comments..
every thing works fine in post and get ..
but my problem it's when i try to make "submit"button of replies disable to prevent anyone from pressing it without typing..
so i use javascript but the code didn't work fine ..
first it work only with the last element of #foreach .. after i use the name as "class" instead of "id" it work for all elements
but the problem is .. if i typing in first reply input text for example .. the button didn't enable .. but if i typing at last reply input text .. all buttons enable ..
I want the code work for each reply .. only when some one typing in that input text ..
JavaScript
<script>
var $inputreply = $('.replies');
var $buttonreply = $('.replysubmit');
setInterval(function () {
if ($inputreply.val().length > 0) {
$buttonreply.prop('disabled', false);
}
else {
$buttonreply.prop('disabled', true);
}
}, 100);
</script>
View which have loop #foreachof comments and replies for each comment
<section class="comment-list">
#foreach (var item in ViewBag.CommentsList)
{
<article class="row">
<div class="col-md-10 col-sm-10">
<div class="panel panel-default arrow left">
<div class="panel-body">
<header class="text-left" style="direction:rtl;">
<time class="comment-date" datetime="16-12-2014 01:05"><i class="fa fa-clock-o"></i> #item.CommentDateTime</time>
</header>
<div class="comment-post">
<p>#item.Comment</p>
</div>
<p class="text-right"><a class="btn btn-default btn-sm replybtn"><i class="fa fa-reply"></i> reply</a></p>
</div>
</div>
<!--ReplyBox-->
#if (Request.IsAuthenticated)
{
using (Html.BeginForm("Reply", "Home", new { #id = #item.PostID, #commentId = #item.ID }, FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="input-group" style="direction:ltr;">
<input type="text" class="replies form-control" placeholder="" name="replies" />
<span class="input-group-btn">
<button class="replysubmit btn btn-primary" type="submit">Reply</button>
</span>
</div>
}
}
else
{
<div class="form-horizontal">
<div class="alert alert-danger replybox" style="display:none;">
<span>please login to reply</span>
</div>
</div>
}
#foreach (var subitem in ViewBag.Relies)
{
if (#subitem.CommentID == #item.ID)
{
<article class="row">
<div class="col-md-9 col-sm-9">
<div class="panel panel-default arrow left">
<div class="panel-heading left">Reply</div>
<div class="panel-body">
<header class="text-left">
<time class="comment-date" datetime="16-12-2014 01:05"><i class="fa fa-clock-o"></i> #subitem.ReplyDate</time>
</header>
<div class="comment-post">
<p>#subitem.CommentReply</p>
</div>
</div>
</div>
</div>
<div class="col-md-2 col-sm-2 col-md-offset-1 col-sm-offset-0 hidden-xs">
<figure class="thumbnail">
<img class="img-responsive" src="http://www.keita-gaming.com/assets/profile/default-avatar-c5d8ec086224cb6fc4e395f4ba3018c2.jpg" />
<figcaption class="text-center">#subitem.UserName</figcaption>
</figure>
</div>
</article>
}
}
</div>
<div class="col-md-2 col-sm-2 hidden-xs">
<figure class="thumbnail">
<img class="img-responsive" src="http://www.keita-gaming.com/assets/profile/default-avatar-c5d8ec086224cb6fc4e395f4ba3018c2.jpg" />
<figcaption class="text-center">#item.userName</figcaption>
</figure>
</div>
</article>
<br />
}
</section>
The selector $('.replysubmit') returns all the items with that css class, hence updating the disabled property of all those elements, not just the one closest to the input element.
You should use a relative selector to get the submit button inside the form where the reply input element is.
jQuery closest() and find() methods will be handy
This should work
$(function () {
$('.replysubmit').prop('disabled', true); // Disable all buttons when page loads
// On the keyup event, disable or enable the buttons based on input
$(".replies").keyup(function() {
if ($(this).val().length > 0) {
$(this).closest("form").find(".replysubmit").prop('disabled', false);
} else {
$(this).closest("form").find(".replysubmit").prop('disabled', true);
}
});
});

Ng-repeat not working expression shows and then disappears immediately

I am creating a list of users on this page using ng-repeat. When the page is refreshed the expression that is supposed to appear shows up for a split second and then disappears without any trace of the object that should be repeated. This is the code
<div class="row" data-ng-controller="createUserProfileController as dashboard">
<h2 class="text-center">Find Students Near By</h2>
<hr />
<div class="col-md-6" id="map-canvas"></div>
<div class="col-md-4 pull-right">
<div class="panel-success">
<div class="panel-heading">
<h3 class="text-center">List of Datalus Users</h3>
</div>
<hr />
<div ng-repeat="userProfile in dashboard.items" class="panel">
<div class="panel-heading">
<h4 class="panel-title text-center">
<a data-parent="#accordion1" href="/courses/moreinfo/{{userProfile.id}}">
{{userProfile.firstName}}
</a>
</h4>
</div>
</div>
</div><!-- /.cols -->
</div>
</div>
In your code there is no error. Might be you are doing changes from somewhere else. Here I implemented your code in jsfiddle.
angular.module("app", [])
.controller("createUserProfileController", ["$scope", function($scope){
var c = this;
c.items = [
{
id: 1,
firstName: 'hello'
}, {
id: 2,
firstName: 'bufellow'
}
];
}]);

Categories