Bootstrap Accordion in Angular with dynamic length - javascript

I am learning Angular 4 in combination with Bootstrap.
The idea is to receive an array of lists from my backend server, which works fine, and to display each list in one single accordion (collapse).
My problem is the following: As the array of lists varies in length, I have to create the elements dynamically, which creates this error:
zone.js:569 Unhandled Promise rejection: Template parse errors:
Can't bind to 'target' since it isn't a known property of 'tr'. (" <tbody>
<tr *ngFor="let listObj of lists" class="panel panel-default" data-toggle="collapse" [ERROR ->]data-target="#collapse{{listObj.index}}">
<td><div class="panel-group">
<div class="p"): ng:///AppModule/TestComponent.html#8:90 ; Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:
Can't bind to 'target' since it isn't a known property of 'tr'. (" <tbody>
<tr *ngFor="let listObj of lists" class="panel panel-default" data-toggle="collapse" [ERROR ->]data-target="#collapse{{listObj.index}}">
<td><div class="panel-group">
<div class="p"): ng:///AppModule/TestComponent.html#8:90
How it should look like:Tested with hardcoded HTML
My HTML:
<table class="table table-hover ">
<thead>
<tr>
<th>Description</th>
<th>Author</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let listObj of lists" class="panel panel-default" data-toggle="collapse" data-target="#collapse{{listObj.index}}">
<td><div class="panel-group">
<div class="panel-heading">
{{listObj.list.listDescription}}
{{listObj.index}}
</div>
<div id="collapse{{listObj.index}}" class="panel-collapse collapse">
<ul class="list-group">
<li *ngFor="let item of listObj.list.listItems" class="list-group-item col-lg-12">{{item}}</li>
</ul>
</div>
</div>
</td>
<td>{{listObj.list.listAuthorName}}</td>
<td>
<div class="input-group">
<input type="text" class="form-control" #listAdd>
<span class="input-group-btn">
<button (click)="onClickAddItem(list.listId, listAdd.value)" class="btn btn-default" type="button">add</button>
<button class="btn btn-danger" type="button">Delete</button>
</span>
</div>
</td>
</tr>
</tbody>
</table>
The array of list-objects is in standard JSON-format
also exuse my english and thank you for your help

I guess you are looking for attribute binding like
[attr.data-target]="'#collapse' + listObj.index"

Related

Ko Bindings after #Html.Partial do not work

I Have the following code cshtml
<div class="container-fluid" id="dvUserData">
<div class="tab-pane fade" id="documentos" role="tabpanel" aria-labelledby="documentos-tab">
#Html.Partial("Documentos")
<div class="col-md-3">
<button type="submit" class="btn btn-primary botao-vert" data-bind="click: editData">SALVAR</button>
</div>
</div>
and the following binding
ko.applyBindings(model, document.getElementById("dvUserData"));
But my data-bind="click: editData" does not work, the click is not performed. But if i put the div class="col-md-3" before the #Html.Partial("Documentos") the bindings work.
I have no idea why, I looked for posts here but could not find anything similar.
Thanks in advance for any help.
---EDITED
The Partial
<div class="row" id="dvDocument">
<form role="form">
<div class="row">
<div class="col-12">
<table class="table tabela-documentos">
<tbody data-bind="foreach: documentsReturn().documentTypes">
<tr class="bg-cinza">
<td>
<div class="aviso-sucesso" data-bind="visible : hasAllDocuments()"></div>
<div class="aviso-critica" data-bind="visible : !hasAllDocuments()"></div> <span data-bind="text: Description"></span>
</td>
<td>
<span class="d-none" data-bind="value: IdTypeDocument"></span>
<a class="btn btn-secondary" data-bind="click: function () { $parent.saveTypeDocument(IdTypeDocument); $('.alerta-form2').hide();}" data-toggle="modal" data-target="#modalDocumento">
ADICIONAR
</a>
</td>
</tr>
<!-- ko foreach: DocumentsArray() -->
<tr>
<td><i class="fa fa-file-text-o" aria-hidden="true"></i> Inclusão: <span data-bind="text: NewDate"></span></td>
<td>
<i class="fa fa-times pointer" data-toggle="modal" data-target="#modal-confirmation" aria-hidden="true" data-bind="visible : !frombase(),
, click: function(){ #*if (confirm('Deseja realmente deletar o documento?')) {*# $parent.savePath(Path); #*}*# }"></i>
</td>
</tr>
<!-- /ko-->
</tbody>
</table>
</div>
</div>
<div class="alert-button">
</div>
</form>
</div>
I forgot to mention that i have another javascript file that bindings the div document with a different model.
Press the F12 and check for any knockout js init (ko.applyBindings) error.
If there is any, fix it and try.
If no error exist, then make sure you have set a value to the model.Name() property by debugging the code.
and check your partial view and see whether you have narrow down the scope/ binding context to another complex property of you model which also has the Name property.
It would be better if you could give more info about partial view binding declaration and the how you are setting / loading the initial values to your model.
After looking for the solution and talk with some friends i found out what was the problem. I was binding the major div, that had the div id "documentos", and another information, and this was the problem.
I remove the binding of dvUserData, and put the binding in all the div that i had, including creating a new div just for the button.
This is how my div "documentos" is now.
<div class="tab-pane fade" id="documentos" role="tabpanel" aria-labelledby="documentos-tab">
#Html.Partial("Documentos")
<div class="alert-button mb-3">
<div id="dvDocumentValidate">
<button type="submit" class="btn btn-primary botao-vert" data-bind="click: editData">SALVAR</button>
</div>
</div>
</div>
And my bindings
ko.applyBindings(model, document.getElementById("dvLoading"));
ko.applyBindings(model, document.getElementById("personaldata"));
ko.applyBindings(model, document.getElementById("address"));
ko.applyBindings(model, document.getElementById("databank"));
ko.applyBindings(model, document.getElementById("dvDocumentValidate"));
ko.applyBindings(model, document.getElementById("corporatedata"));

Protractor find a certain value inside td class

I have been looking on many different examples how to iterate a table.
If I am using code below for selenium I get exactly what I want.
driver.findElement(By.xpath("//td[contains(.,'Apple Pomace')]"));
though I would like to instead to iterate the code and find the value below:
<td class="ng-binding">Apple Pomace</td>
Notice there are Apple Pomace in two places
See image
there is my table:
<div class="col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1">
<h3 ng-show="searchQuery" class="page-header page-header-sm"><span translate="TITLE_SEARCH_RESULTS" class="ng-scope">Search Results</span> <span class="label label-default ng-binding" ng-bind-html="searchQuery">Apple Pomace</span></h3>
<h3 ng-show="!searchQuery" class="page-header page-header-sm ng-scope ng-hide" translate="TITLE_ALL_PRODUCTS">All Products</h3>
<div class="alert-info ng-hide" ng-show="confirmation">
<p class="ng-binding"></p>
</div>
<table class="table table-striped table-bordered table-condensed">
<tbody><tr>
<th translate="LABEL_IMAGE" class="ng-scope">Image</th>
<th translate="LABEL_PRODUCT" class="ng-scope">Product</th>
<th translate="LABEL_DESCRIPTION" class="ng-scope">Description</th>
<th translate="LABEL_PRICE" class="ng-scope">Price</th>
<th></th>
</tr>
<!-- ngRepeat: product in products --><tr data-ng-repeat="product in products" class="ng-scope" style="">
<td><img src="/public/images/products/apple_pressings.jpg" class="img-responsive img-thumbnail" style="width: 200px" ng-click="showDetail(product.id)"></td>
<td class="ng-binding">Apple Pomace</td> //here is the item I want to fetch 'Apple Pomace'
<td><div ng-bind-html="product.description" class="ng-binding">Finest pressings of apples. Allergy disclaimer: Might contain traces of worms. Can be sent back to us for recycling.</div></td>
<td class="ng-binding">0.89</td>
<td>
<div class="btn-group">
<a class="btn btn-default btn-xs" ng-click="showDetail(product.id)"><i class="fa fa-eye"></i></a>
<a class="btn btn-default btn-xs ng-hide" ng-click="addToBasket(product.id)" ng-show="isLoggedIn()"><i class="fa fa-cart-plus"></i></a>
</div>
</td>
</tr><!-- end ngRepeat: product in products -->
</tbody></table>
</div>
I hade made following code but it's not correct in my opinion.
element.all(by.css('.ng-binding')).each(function(element, index)
{
element.getText().then(function (text)
{
});
})
notice I got 'Apple Pomace' in two places that's why its important to iterate through the td-class 'ng-binding'.
Could someone help me
Thank you in advance
In case if you want to just access the td you can use this:
element(by.cssContainingText('.table td', 'Apple Pomace'))
In case if you would like to filter the rows in the table by the product and get the element you can use below code snippet:
element.all(by.repeater('product in products')).filter(function(elem, index) {
return elem.element(by.cssContainingText('td', 'Apple Pomace')).isPresent();
}).first();

AngularJS: how to update key of $scope associate array on checkbox select/unselect?

my PHP programming return following JSON via AJAX which is being set in a scrope variable $scope.roleAssigned which then eventually generates an Accordian with a table and checkbox:
$json2 = '{"status":"OK","data":[{"label":"Admin","id":1,"rights":[{"id":"1","label":"create","selected":"1"},{"id":"2","label":"update","selected":"0"},{"id":"3","label":"delete","selected":"0"},{"id":"4","label":"lists","selected":"0"}]},
{"label":"Normal User","id":2,"rights":[{"id":"1","label":"create","selected":"1"},{"id":"2","label":"update","selected":"1"},{"id":"3","label":"delete","selected":"1"},{"id":"4","label":"lists","selected":"0"}]}]}';
Now on button click I want to send back same data back to PHP in JSON. selected field is telling whether someone clicked on checkbox or not. So for instance {"id":"1","label":"create","selected":"1"} could be {"id":"1","label":"create","selected":"0"}
Is there any Angular Way to update key of scope array on checkbox click? I don't want to generate iterating DOM(jQuery way).
HTML
<div class="dynamic" ng-repeat="role in roles | orderBy:sortType:sortReverse | filter:queryRoles ">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title text-center">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse_{{role.id}}">
{{role.label}}
</a>
</h2>
</div>
<div id="collapse_{{role.id}}" class="panel-collapse collapse">
<div class="panel-body text-center">
<table id="roles-table" class="table table-striped" align="center">
<thead>
<tr>
<td>Droit</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="right in role.rights">
<td>{{right.label}}</td>
<td>
<input data-rid="{{role.id}}" type="checkbox" ng-checked="right.selected == 1">
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
Let me know if possible.
You can make use of $parent.$index and $index
<input data-rid="{{role.id}}" type="checkbox" ng-checked="right.selected == 1" ng-click="checkIt($parent.$index, $index, right.selected)">
$scope.checkIt= function(parentIndex, index, selected){
selected = (selected === "1") ? "0" : "1";
$scope.roles[parentIndex].rights[index].selected = selected;
};

Text in panel body is not showing in rows

What need is in script in panel body text to be shown in rows for every data in ng-repeat. On left to be data.name and right to be icon. With current code data is not showing on separate rows, it is messy.
<script type="text/ng-template" id="field_renderer.html">
<div class="col-md-6" ng-repeat-start="data in data.children">
<div class="row">
<label>
<input type="checkbox" value="{{data.name}}" ng-model="data.isSelected">
{{data.name}}
</label>
<span ng-if="data.children.length > 0">
<i class="pull-right glyphicon" data-ng-click="data.showDetails = !data.showDetails"
ng-class="{'pull-right glyphicon glyphicon-plus': !data.showDetails, 'pull-right glyphicon glyphicon-minus': data.showDetails}"></i>
</span>
</div>
</div>
<div ng-repeat-end ng-if="data.showDetails" ng-include="'field_renderer.html'"></div>
</script>
<div class="panel-group">
<div ng-repeat-start="data in reportsvm.filters" class="panel panel-default">
<div class="panel-heading clickable" data-ng-click="reportsvm.showDetails(data)">
<h4 class="panel-title">
{{data.name}}
<i ng-class="{'pull-right glyphicon glyphicon-plus': !data.showDetails, 'pull-right glyphicon glyphicon-minus': data.showDetails}"></i>
</h4>
</div>
</div>
<div class="panel-body small" ng-if="data.showDetails" ng-repeat-end ng-include="'field_renderer.html'"></div>
</div>
Here is screnshot of how it is looking.
As you can see for location that two checkboxes I need to be one after another in separate rows. Also in Program i need to be in separate rows and in each row that icon to be on right.
UPDATE - CURRENT SOLUTION
<table class="table">
<tbody>
<tr ng-if="data.name === 'Location'">
<td class="noBorder" colspan="2">
<button data-ng-click="reportsvm.changeLocation(data, true)" data-ng-class="" class="btn btn-default btn-sm">
Regions</button>
<button data-ng-click="reportsvm.changeLocation(data, false)" data-ng-class="" class="btn btn-default btn-sm pull-right">
State/Territory</button>
</td>
</tr>
<tr ng-repeat-start="data in data.children">
<td class="noBorder">
<label>
<input type="checkbox" value="{{data.name}}" ng-change="reportsvm.changeValue(data)" ng-model="data.isSelected">
{{data.name}}
</label>
</td>
<td class="noBorder">
<span ng-if="data.children.length > 0">
<i class="pull-right glyphicon" data-ng-click="data.showDetails = !data.showDetails"
ng-class="{'pull-right glyphicon glyphicon-plus': !data.showDetails, 'pull-right glyphicon glyphicon-minus': data.showDetails}"></i>
</span>
</td>
</tr>
<tr ng-repeat-end ng-if="data.showDetails">
<td class="noBorder" ng-include="'field_renderer.html'"></td>
</tr>
</tbody>
</table>
It makes sense. You try to create a new checkbox for every column.
Bootstrap tries to fill in the space for col-md-6 (2-column layout).
<div class="col-md-6" ng-repeat-start="data in data.children">
One solution would be to put the ng-repeat in the row element:
<div class="col-md-6">
<div class="row" ng-repeat-start="data in children>
<!--rest of the code ....-->
</div>
</div>

How to map data coming dynamically into the designed table individually in respective form fields using jquery?

My data in the table is coming from back-end or user can manually enter the values in the table. Now my question is 'how to map those values again into the form, from which user was able to enter values into the table using jquery'? This back mapping of data from table to form is done on click of edit link which is present in front of every entry of my data in the table.
<html>
<head>
<style>
.dropdown>a:after {
display: none;
}
.glyph-ok-size, .glyph-remove-size {
font-size: 15px;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$(".add_edit_panel").hide();
$("#addNew").click(function() {
$(".add_edit_panel").slideToggle();
});
});
function edit(paramID){
$(".add_edit_panel").slideDown();
}
</script>
</head>
<body>
<cu:secured hasPermission="CORE_CUSTOMER_DATES_CREATE"
var="canCreateOrgDates"></cu:secured>
<cu:secured hasPermission="CORE_CUSTOMER_DATES_UPDATE"
var="canUpdateOrgDates"></cu:secured>
<cu:taskView taskFlowData="${taskFlowData}"
taskFlowDefinition="${taskFlowDefinition}" id="dateRange"
renderTasks="false"
title="task.title.organization.daterange"
tasks="${taskFlowData.availableTasks}">
</cu:taskView>
<div class="row">
<form action="save.action" method="post">
<div class="col-sm-6">
<div class="panel add_edit_panel">
<div class="panel-heading">${fmt:message('dateRange.panel.add.edit') }</div>
<core:text name="orgDateObj.periodName"
label="${fmt:message('org.daterange.name') }"
required="false"
maxlength="20"
placeholder="${fmt:message('org.daterange.name') }">
</core:text>
<div class="row">
<div class="col-sm-6">
<core:date id="startDate" name="orgDateObj.startDate" label="${fmt:message('org.daterange.startdate')}"
placeholder="${fmt:message('org.daterange.startdate')}"
primary="false" required="true" />
</div>
<div class="col-sm-6">
<core:date id="endDate" name="orgDateObj.endDate" label="${fmt:message('org.daterange.enddate')}"
placeholder="${fmt:message('org.daterange.enddate')}"
primary="false" required="true" />
</div>
</div>
<div class="row">
<div class="col-sm-12">
<label class="default" style="float=left"><core:checkbox
name="orgDateObj.isDefault" id="isDefault"
label="${fmt:message('org.daterange.defaultdate')}"
checked="true" indicator="true"
disabled="false"
title="${fmt:message('org.daterange.describe.defaultdate')}" />
</label>
<div class="btn-panel-margin">
<button id="save" type="submit" class="btn btn-ar btn-primary" data-allow-dirty="allow">
${fmt:message('button.save')}
</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="row">
<div class="col-sm-6">
<div class="panel">
<div class="panel-heading">${fmt:message('dateRange.panel.listing') }</div>
<div class="row">
<div class="col-sm-12" style="overflow-x: scroll">
<table data-grid-sortable class="table table-striped table-condensed table-responsive sort-display-table">
<thead>
<tr>
<th data-column-sortable class="column-md sorted"><fmt:message key="table.date.name"/>
<span class="caret column-sort-direction"/>
</th>
<th data-column-sortable class="column-md"><fmt:message key="table.startdate"/>
<span class="caret column-sort-direction"/>
</th>
<th data-column-sortable class="column-md"><fmt:message key="table.enddate"/>
<span class="caret column-sort-direction"/>
</th>
<th data-column-sortable class="column-sm"><fmt:message key="table.default"/>
<span class="caret column-sort-direction"/>
</th>
<th data-column-sortable class="column-sm"></th>
</tr>
</thead>
<tbody id="tbody">
<c:forEach var="orgDate" items="${orgDates}">
<tr>
<td class="column-md">${orgDate.periodName}</td>
<td class="column-md">${orgDate.startDate}</td>
<td class="column-md">${orgDate.endDate}</td>
<td class="column-sm">
<c:choose>
<c:when test="${orgDate.isDefault == '1'}">
<span class="glyphicon glyphicon-remove glyph-remove-size"></span>
</c:when>
<c:otherwise>
<span class="glyphicon glyphicon-ok glyph-ok-size"></span>
</c:otherwise>
</c:choose>
</td>
<td class="column-sm">
<div class="row">
<div class="col-sm-12">
<div class="dropdown">
Action<b class="caret"></b>
<ul class="pull-right dropdown-menu">
<li>
<a href="#" id="editButtonId" onclick="edit(${orgDate.orgDateId})" >
<i class="glyphicon glyphicon-pencil margin-right-5"></i>Edit
</a>
</li>
<li>
<a href="#" id="deleteButtonId${orgDate.orgDateId}"><i class="glyphicon glyphicon-trash margin-right-5"></i>Delete
</a>
</li>
</ul>
</div>
</div>
</div>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="btn-panel-margin">
<button id="addNew" type="button" class="btn btn-ar btn-primary" data-allow-dirty="allow">
${fmt:message('button.addnew')}
</button>
</div>
</div>
</div>
</body>
</html>
enter image description here
in edit button give the row index as class and get the value of that row by mapping array index value of 1st row of table equals to array[0] access the array[0] values and place the value of array in form text box i.e
$('#textbox1').val=array[0]['name'];
you can do stuff like this
$('#edit').onclick(function (){
$('#name').val=array[0]['name'];
$('#startDate').val=array[1]['S-Date'];
$('#endDate').val=array[2]['E-Date'];
$('#checkbox').val=array[3]['Checkval'];
});
I wanted to know how your data is formed from Database
In jquery use
x=0;
objectdata.forEach(function(value,indexname,arr), thisValue) {
tabledata['col'+x][indexname]=value;
x++;
}

Categories

Resources