I wanted to develop a table for which data is being fetched via a dataset and the rows are populated in a table with accordion category names.
#accordion-data is a blank div and this whole functionality is supposed to be inside it.
fetchDataAccordion(datasetNum) {
const self = this;
for (let c of self.categoryNames) {
console.log(c);
$("#accordion-data").append(`
<div class="nested-accordion">
<h3>${c}</h3>
<div class="comment">
<table id="${c}-data">
<colgroup>
<col style="width:2%"/>
<col style="width:6%"/>
<col style="width:10%" />
<col style="width:28%"/>
<col style="width:16%"/>
</colgroup>
<tr class="bfm-rows">
<th class="data-table-headers" rowspan="2">S.No</th>
<th class="data-table-headers" rowspan="2">Category</th>
<th class="data-table-headers" rowspan="2">BI Features</th>
<th class="data-table-headers" rowspan="2">Details</th>
<th class="data-table-headers" rowspan="2">User Weightage</th>
</tr>`);
self.fetchDataset(datasetNum).then(
response => {
let data = response.data;
for (let i of data) {
if (i.Category == c) {
$("#accordion-data").append(`
<tr class='bfm-rows'>
<td style="text-align:center">${i.Sno}</td>
<td>${i.Category}</td>
<td>${i.BIFeatures}</td>
<td>${i.Details}</td>
<td>
<select class="user-weightage-dropdown form-select" id="uw-${i.Sno}">
<option value="-1" style="display:none">Select Weightage</option>
<option value="0" class="user-weightage-options">0 - Donot Require this functionality</option>
<option value="10" class="user-weightage-options">10 - This is nice to have functionality</option>
<option value="20" class="user-weightage-options">20 - This is functionality is optional</option>
<option value="30" class="user-weightage-options">30 - This functionality is needed</option>
<option value="40" class="user-weightage-options">40 - Important functionlaity</option>
<option value="50" class="user-weightage-options">50 - Extremely important functionality</option>
</select>
</td>
</tr>
`);
// }
$("#accordion-data").append(`</table>
</div>
</div>`);
}
});
}
}
I also have a JQuery written as:
$('.nested-accordion').find('.comment').slideUp();
$('.nested-accordion').find('h3').click(function() {
$(this).next('.comment').slideToggle(100);
$(this).toggleClass('selected');
});
I tried the above method but the table closes before the rows are populated resulting in following
Table View
I want the table to have those rows in them too. Here the table is closing after the heading row and the below rows are without any parent table.
Kindly help!
There are a few things I would do here.
First, I would wrap the row of table headings (<th> elements) in a <thead> element. I'm not familiar with the rowspan attribute, but I get a wonky render if I don't include the <thead>.
Next, I would consider using a simple templating library so that I don't have to include all of that HTML markup in my JavaScript. Handlebars is one but one example.
When it comes to your accordion behavior, I think that it is broken due to the timing. I think that your jQuery code executes before your table rows have been populated. You could get around this by moving the jQuery code into your fetch handler, after #accordion-data has been fully appended to; however, my preferred approach would be to use event delegation. Basically, we will tell jQuery to listen for clicks on our #accordion-data element whose source is h3 elements:
$('#accordion-data').on('click', 'h3', function () {
$(this).next('.comment').slideToggle(100);
$(this).toggleClass('selected');
});
Finally, we might want to make sure that our .comment elements are collapsed (hidden) on their initial render, which we can do with CSS:
.comment {
display: none;
}
Please see this fiddle for the full example.
Related
I have created a dynamic drop down list. I want to access the value selected from the dynamically created drop down.
My HTML file
<!DOCTYPE html>
</head>
<body>
<table align="center" cellspacing="3" cellpadding="3">
<tr>
<td>County Name: </td>
<td><select id="county"><option value="">Select county</option></select></td>
</tr>
<tr>
<td>City: </td>
<td><select id="city"><option value="">Select city</option></select></td>
</tr>
</table>
<button class="btn" onclick="doThis()"">Go</button>
</body>
My js file:
function doc(id){return document.getElementById(id);}
function buildCounty(){
var opts=doc('county').options;
for(var i=0;i<arr.length;i++){
opts[opts.length]=new Option(arr[i][0],arr[i][0]);
}
doc('county').onchange=function(){
this.blur();
var val=this.value;
if(!val){return;}
var co=doc('city').options;
co.length=1;
for(var j=0;j<arr.length;j++){
if(arr[j][0]!==val){continue;}
else{
var temp=arr[j][1];
for(var k=0;k<temp.length;k++){
co[co.length]=new Option(temp[k],temp[k]);
}
break;
}
}
}
}
function doThis(){
}
window.onload=buildCounty;
</script>
On click of the button, doThis() function existing in js file is called. In that function, I want to access the value selected in the 2nd (City list) dropdown.
In jQuery you can do below:
I can see that you don't have any value for city option. Was that the reason you were not able to get a value? If yes, then you need to populate the values too in your markup.
function doThis() {
console.log($('#city').val());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table align="center" cellspacing="3" cellpadding="3">
<tr>
<td>County Name: </td>
<td><select id="county"><option value="">Select county</option></select></td>
</tr>
<tr>
<td>City: </td>
<td><select id="city"><option value="SomeValue">Select city</option></select></td>
</tr>
</table>
<button class="btn" onclick="doThis()" ">Go</button>
It looks like you might be able to leverage more of jQuery for this list.
First, in Jquery there is no need for this line:
function doc(id) { document.getElementyById(id); }
You are able to use a CSS selector to get an element using jQuery:
$("#id-of-element");
You can even assign it to a variable:
var countyDropdown = $("#county");
Additionally, one of the "better" ways of running jQuery is to place the script tag at the end of your document and then wait for the document to raise the ready event:
$(document).ready(function () { .... });
Here is a quick codepen I put together that leverages jQuery to dynamically populate a dropdown from the selection in another dropdown. It also sets up the go button to do something when clicked.
codepen-dynamic-dropdown-selection
I create a table with dynamic data from mysql. He seems to :
screen
When I click on the delete button from the second row, and make an alert js with the value of id, he save the id from the first row and not in the row where I cliqued.
My Views :
$('.Btrash').click(function() {
//var id_stream = $('#id_stream').val();
var id_stream = $('#id_stream').attr('value');
var id_compte = $('#id_compte').val();
alert(id_stream);
});
<div class="row" id="Tstream">
<table class="table table-striped table-bordered table-list">
<thead>
<tr>
<th>Feeds</th>
<th>Data request</th>
<th>Begin Stream</th>
<th>End Stream</th>
<th><em class="fa fa-cog"></em></th>
<th>Status</th>
<th>Access to Data</th>
</tr>
</thead>
<tbody >
<?php foreach ($aAllRequestByIdUser as $aRequestByIdUser) : ?>
<tr>
<td class="vert-align">
<input type="hidden" id="id_compte" value="<?= $iIdCompte ?>">
<input type="text" id="id_stream" value="<?= $aRequestByIdUser['id_Stream'] ?>">
...
My alert always show 74.
Can you help me to find a solution?
Thanks
First let me explain a bit about jquery selectors. This code of yours
var id_stream = $('#id_stream').attr('value');
selects all the items with the id of #id_stream, and returns the first value.
If you want to get the ID of the row clicked, then you should select the row first. But since you haven't shared the rest of your code, i can only assume the rest. There are several ways of doing so, and this is one of them.
1 ) Get the parent of $(this) >
2 ) Then get the first sibling of it
3 ) Finally find input and get val().
Or you can do it by Jquery's closest function. But as i said, first i need to see the rest of your code.
I have built a semi-custom DataGrid based on a table with fields that auto-populate based on a Service call, An intended behavior in the DataGrid is the ability for the user to revise an entry in the system (in this case, Documents) so that the user can select an action and "Replace" the file, and its File Type. The actual markup looks like this:
<form action="#" method="post" ng-model="OtherDocumentsForm" style="margin-top: 15px;">
<h3 style="margin: 0;">Additional Documents</h3>
<table>
<tr>
<th>File Type</th>
<th>File Name</th>
<th>Date</th>
</tr>
<tr ng-repeat="record in DocumentsOther track by $index" id="row-{{record.file_url}}">
<td>
<span data-document-type="{{record.file_type}}" data-document-id='{{record.document_id}}'>{{record.file_type}}</span>
<select ng-model="newDocumentType" id="replace-file-doctype-{{record.document_id}}" placeholder="Choose file Type" ng-show="$scope.replaceFile" data-document-id="{{record.document_id}}" class="replaceComboBox"> <!-- Note replaceFile -->
<option label="" value="" selected="selected"></option>
<option label="PDF" value="pdf">PDF</option>
<option label="Image" value="image">Image</option>
</select>
</td>
<td>
<div ng-if="record">
{{record.document_name}}
<!-- Replace Action-->
<button class="replaceAssociatedRecord" ng-click="ClearAssociatedFile($event, this, '{{record.file_url}}', '{{record.document_id}}');" data-document-type="{{record.file_type_raw}}">Replace</button>
<input type="file" ng-model="replaceFileField" id="replace-file-{{record.document_id}}" data-document-id="{{record.document_id}}" data-document-type="{{record.file_type_raw}}" onclick="checkIfAssocFileDefined(this);" ng-show="replaceFile" class="replaceFileField" /> <!-- Note replaceFile -->
</div>
</td>
<td>
{{record.date_created | dateConsistent}}
</td>
</tr>
</table>
<button ng-click="addUncategorizedFile($event)" style="margin: 5px auto 15px; display: block;">Upload additional file</button>
</form>
As you can probably see, one of the issues that is present is that $scope.replaceFile is called across the board. This value gets set to true when $scope.ClearAssociatedFile() (code below) is called in the replace action, so every field gets unhidden. This was a serious oversight on my end and I am wondering, what would be the best approach to re-implement the components here so that I can split off replaceFile (tied to ng-show, and uninitalized inside the parent controller) so its independent enough to where it can be altered once the event of ClearAssociatedFile is selected?
$scope.ClearAssociatedFile = function(event, elem, parentClassName, inheritDocumentId) {
event.preventDefault();
event.stopPropagation();
//TODO reconfigure to use event
//document.getElementById("row-"+parentClassName).children[0].children[0].innerHTML = "";
event.currentTarget.parentElement.parentElement.parentElement.children[0].children[0].innerHTML = "";
//event.currentTarget.parentElement.parentElement.parentElement.children[0].children[1].style.display = "inline-block"
//document.getElementById("row-"+parentClassName).children[1].children[0].children[0].innerHTML = "";
event.currentTarget.parentElement.parentElement.parentElement.children[1].children[0].children[0].innerHTML = "";
//document.getElementById("row-"+parentClassName).children[1].children[0].children[1].style.display = "none";
event.currentTarget.parentElement.parentElement.parentElement.children[1].children[0].children[1].style.display = "none";
//event.currentTarget.parentElement.parentElement.parentElement.children[1].children[0].children[2].style.display = "inline-block";
//Revise the File Type field to its default.
document.getElementById("replace-file-doctype-"+inheritDocumentId).value = event.target.attributes[2].value;
//Show existing fields
//eval($scope.replaceFile+inheritDocumentId = true);
var replaceFileKey = "replaceFileItem"+$filter('convert_dashes')(inheritDocumentId);
$scope[replaceFileKey] = true;
};
In your controller, declare the following variable
$scope.replaceFileKeys = {};
Replace the last 2 lines in the ClearAssociatedFile function with the following
var replaceFileKey = inheritDocumentId;
$scope.replaceFileKeys[replaceFileKey] = true;
Update ng-show as follows
ng-show="$scope.replaceFileKeys[record.document_id]"
With the above change, only the item that you interact with is hidden. Let me now if you have questions about the change.
I am able to select multiple rows, but I would like to be able to select those datas in different tables on the same page. At the moment, when I select a row in the first table, it selects it in the second table as well, but I would like them to be independent. Anyone has an idea ?
Below is my html code
<div class="row" ng-show="{{ adultNumber }}">
<div class="col-md-8">
<h1>Adult 1</h1>
<table class="table table-bordered">
<tr ng-repeat="extra in extras" ng-class="{'selected': extra.selected}" ng-click="select(extra)" ng-model="radioExtrasAdult1">
<td ng-bind="extra.name"></td>
<td ng-bind="extra.price"></td>
</tr>
</table>
</div>
</div>
<div class="row" ng-show="{{ adultNumber >= 2 }}">
<div class="col-md-8">
<h1>Adult 2</h1>
<table class="table table-bordered">
<tr ng-repeat="extra in extras" ng-class="{'selected': extra.selected}" ng-click="select(extra)" ng-model="radioExtrasAdult2">
<td ng-bind="extra.name"></td>
<td ng-bind="extra.price"></td>
</tr>
</table>
</div>
</div>
Below angular js
$http.get('json/extras.json')
.then(function(res){
$scope.extras = res.data;
});
$scope.select = function(item) {
item.selected ? item.selected = false : item.selected = true;
}
$scope.submit = function(x) {
var x = $filter("filter")($scope.extras, {
selected: true
}, true);
console.log(x);
}
Thank you.
The thing is, when you select an object in a table, you modify its attribute to tell it it is selected. Given the fact that you are using the same object in the other table, it is updated too and so it is also selected.
There are different things you can do about it,
Make a deep copy of the objects you display so that you display one copy per table and so you don't modify the two contents simultaneously. For this, use angular.copy.
Modify different attributes on the same object when performing selection. You could for instance use item.selected[0] for the first table and item.selected[1] for the second one. The advantage of this solution is that all data is centralized in the same object. Still, you have to pass an aditional parameter to your select function to tell in which table you are selecting (0 or 1)
Hope it helped !
hello everyone i have some trouble returning a result from a function ,
i made a select input with ng-change the result of ng-change is used by an API then displays the result in a table the issue is i can't use the result out of the function
Here's my html page
<select ng-model="dvdv" ng-change="update()" class="form-control" >
<option value="" disabled selected>Veuillez sélectionner un DVD</option>
<option ng-repeat="d in dvd" value="{{d}}"> {{d}} </option>
</select>
The table were data should be displayed
<table class="table table-bordered" >
<thead><tr class="infoti" >
<th>Id Dev</th>
<th>Nom Dev </th>
<th>Nom Ecu</th>
<th>Etat</th>
<th>Action</th>
<tr>
</thead>
<tbody>
<tr dir-paginate=" dev in devs | itemsPerPage:7| filter: search">
<td>{{dev[0]}}</td>
<td>{{dev[1]}}</td>
<td>{{dev[2]}}</td>
<td>Non Validé</td>
<td><button class="btn btn-default">Validé</button></td>
</tr>
</tbody>
</table>
and this is the Function am using to get the data from select input by ng-change and am consuming
$scope.devs=[[]]
$scope.update=function(){
console.log($scope.dvdv)
$http.get("/dev?nommag="+$scope.dvdv)
.success(function(data){
$scope.devs = data ;
console.log($scope.devs)
})
}
here's a pic to explain how i want it to work
when i select an option i get the data then displayed but it's not printed in the table below
else it work for a static so there's no issue with the syntax or ng-repeat
If by 'use' you do mean console.log(), you must do in inside the success callback (as #ddepablo suggests).
If instead by 'use' you do mean "show it in the html page", you simply put a
{{ devs }}
inside your html page, and angular will replace it with $scope.devs value...