Error in while looping in *ngFor in angular - javascript

I have the JSON of single object coming as:
I achieved this data by calling the API in component.ts file which is as follows
/* for auditgorup selecitonm */
this.http.get('http://localhost:8080/api/selections/getAllAuditGroupSelections')
.subscribe((datas: any[]) => {
this.auditSelection = datas;
console.log(this.auditSelection);
// You'll have to wait that changeDetection occurs and projects data into
// the HTML template, you can ask Angular to that for you ;-)
this.chRef1.detectChanges();
// Now you can use jQuery DataTables :
const tables: any = $('#nepal');
this.dataTable = tables.DataTable();
});
The view is as follows
<table id="nepal" class="table table-bodered">
<thead>
<tr>
<th>Selection No</th>
<th>SelectionDate</th>
<th>SelectedBy</th>
<th>PanEximNumber</th>
<th>Name</th>
<th>Address</th>
<th>PhoneNumber</th>
<th>SelectionType</th>
<th>Group Desc</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let nas of auditSelection">
<td>{{nas.selectionId}}</td>
<td>{{nas.selectionDate}}</td>
<td>{{nas.selectedBy}}</td>
<td>{{nas.panEximNumber}}</td>
<td>{{nas.name}}</td>
<td>{{nas.address}}</td>
<td>{{nas.phoneNumber}}</td>
<td>{{nas.selectionType}}</td>
<td>{{nas.assignmentAudit.auditorGroup.groupDesc}}</td>
</tr>
</tbody>
</table>
At this last line of <td>{{nas.assignmentAudit.auditorGroup.groupDesc}}</td> I cannot get the required value.
The output display should be "g1".

I am unable to comment, so adding it over here. assignmentAudit is an array, so try accessing using index

As per the analysis of the JSON structure the assignmentAudit is an array
so you can only access it with the index positions.
If you are sure the assignmentAudit is an array with single value then you can use
<td>
{{nas.assignmentAudit[0].auditorGroup.groupDesc}}
</td>
If assignmentAudit has multiple values and is not deterministic you can try
<td>
<span *ngFor="let assignmentAudit of nas.assignmentAudit">
{{assignmentAudit.auditorGroup.groupDesc}}
</span>
</td>

nas.assignmentAudit[0].auditorGroup.groupDesc
That would work. The section you are trying to access is an array. So picking the first index would then make it defined

groupDesc is insideauditorGroup loop so you cannot do like to get value inside loop. Try like that.
<!-- Angular -->
<ul>
<li *ngFor="let item of nas.assignmentAudit.auditorGroup;">
</li>
</ul>
or <td>{{nas.assignmentAudit.auditorGroup[0].groupDesc}}</td>

Related

Vue, accessing data that's in a different v-for loop

I have a table body in my Vue application where I've got one section of rows being built by a loop around a data object. I then have a separated section that is using a different data object, however, I need to compare a value from it to a value from the other loop in order to get conditional styling
I'm wondering if there is a way where I can send data from the value portion of the first for loop into a method call at the time of that v-for so that I can access it in the summary loop, if that makes sense
Here's the table:
<tbody v-if="selected === 'Stores'">
<tr v-for="(value, manager) in managerNumbers" :key="manager"> <!--Here is where I'm wondering if I can send value to a method call-->
<td v-for="date in dates" :key="date" >
<div v-for="(dataForDate, dateVal) in value.dates" :key="dateVal">
<div v-if="dateVal == date ">
#{{dataForDate.total_categories}}
</div>
</div>
</td>
</tr>
<tr><td colspan="10"></td></tr>
<tr><td colspan="10"></td></tr>
<tr>
<th>
Summary
</th>
<div v-for="store in activeStore" :key="store">
<th :style="'background: ' + (value.qty > store.qty ? '#000' : '#fff')">#{{ store.stock_num }}</th>
</div>
</tr>
</tbody>
You can use a computed method to create a lookup table between both activeStore and managerNumbers and loop over that.
get activeStoreAndManagerNumbers () {
return managerNumbers.map((value, index) => {
return {
value,
store: activeStore[index]
}
})
}
Now you can just loop over this array for both of your v-for:
v-for="(obj, index) in activeStoreAndManagerNumbers"
Now obj.value.qty and obj.store.qty are available in the same loop.

use bootstrap filter in laravel pagination

I am using bootstrap filter in my data table in laravel for searching data. As I am using laravel pagination in I have 30+ pages. But the filter only searching data from the current page. But I want to search data from the full data table ( all the 30 pages)
blade:
<input type="text" id="myInput" class="form-control">
<table class="table table-sm text-sm table-hover">
<thead>
<tr>
<th>Start Date</th>
<th>End Date</th>
<th>No Of Days</th>
</tr>
</thead>
<tbody>
#foreach($leaves_list as $key => $data)
<tr>
<td>
{{$data->leave_start_date}}
</td>
<td>
{{$data->leave_end_date}}
</td>
<td>
{{$data->number_of_days_off}}
</td>
</tr>
</tbody>
</table>
script:
$(document).ready(function(){
$("#myInput").on("keyup", function() {
var value = $(this).val().toLowerCase();
$(".table tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
controller:
$leaves_list = DB::table('employee_leave')
->orderBy('employee_leave_id', 'desc')
->paginate(100);
return view("leaves.index",compact('leaves_list'));
So I want to the search result of all the pages of pagination
Better late than never, huh?
I believe you are around to mid level today, but I hope I can help some other folks on here.
The Laravel Requests return a object than contains a key called "next_page_url".
To check this info, if you dd(); the response, that is what you'll receive:
{#294 ▼ // app\Http\Controllers\FooController.php:22
+"current_page": 1
+"data": array:7 [▶]
+"last_page": 3
[...]
+"next_page_url": "http://127.0.0.1:8000/api/list?page=2"
[...]
}
Is on next_page_url that you gonna have the remaining objects of your requests.
Now, if you need all the objects non-paginated, I suggest you to create another Request, without using paginate methods, but the Where clauses to filtering, in this case.
DB::table('employee_leave')
->orderBy('employee_leave_id', 'desc')
->where('foo', '<>', 'bar');
Don't miss to use this requests only when necessary, avoiding too many requests on the database.
Best regards,
Bruno.

How to bind an object to HTML table in Vue.js, where its properties are dynamically created?

I am using vue.js library for front-end development.
I came a cross a scenario where my JavaScript method returns a list, which has objects, object's number of properties can change each time after method execution.
example my list can contain these type of objects in 2 different executions.
var obj = {
Name : "John",
2020-Jan: 1,
2020-Jul: 2
}var obj = {
Name: "John",
2020-Jan: 1,
2020-Jul: 2,
2021-Jan: 3,
2021-Jul: 4
}
Since Property name is dynamically changes is there any way to bind to HTML ?
<div >
<table>
<thead>
<tr>
<th v-for ="row in Result.Headers">
{{row}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in Result.Data ">
<td>
{{item.2020-Jan}} // Because don't know the number of properties until run time
</td> // No of <td/>'s can change on no of properties.
<td> // exactly don't know how many <td>'s needed there.
{{item.2020-Jul}}
</td> <td>
{{item.2021-Jan}}
</td>
</tr>
</tbody>
</table>
</div>
Is there way to bind these type of object to fronted in vue.js ?
You need to loop over the item's keys again. This will show all the values in the object
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="(value, key, index) in item">
{{value}}
</td>
</tr>
</tbody>
If you want to filter some of them, for instance check that the keys are valid dates you need to add a v-if and use Date.parse to check for this.
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="(value, key, index) in item" v-if="Date.parse(key) !== NaN">
{{value}}
</td>
</tr>
</tbody>
if u wana show all attr-> u can use this:
<ul v-for="item in Result ">
<li v-for="(value,key,index) in item">{{value}}</li>
</ul>
if u wana show all days u can use v-if and compute to complete youself fillter
<div id="app">
<ul v-for="item in Result" >
<li v-for="(value,key,index) in item" v-if="canShow(key)"> index:{{index}}------ key: {{key}} ------ value:{{value}} </li>
</ul>
</div>
<script>
var vue=new Vue({
el:'#app',
data:{
Result:[{
name: 'SkyManss',
2020-Jan: 1,
2020-Jul: 2
},{
name: 'SkyManss2',
2020-Jan: 1,
2020-Jul: 2,
2021-Jan: 3,
2021-Jul: 4
}]
},
computed:{
canShow(){
return function(skey){
return skey.indexOf('-') > -1;
}
}
}
});
</script>
after some research and some of your suggestions I came up with an answer.
<div>
<table>
<thead>
<tr>
<th v-for ="row in Result.Headers">
{{row}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="row in Result.Headers">
{{item[row]}}
</td>
</tr>
</tbody>
</table>
</div>
Javascript code
this.Result.Headers = Object.keys(result.data[0]);
this.Result.Data = result.data;
But this code only worked for the first time. second time data didn't get updated. So I updated JavaScript code to following code.
Vue.set(self.Result, 'Headers', []);
Vue.set(self.Result, 'Result', []);
this.Result.Headers = Object.keys(result.data[0]);
this.Result.Data = result.data;
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. That I got to know from following post.
vue.js is not updating the DOM after updating the array
Thank You All !!!

Show only one element of a panel using Angularjs

I am new to Angularjs and I am trying to figure out how it's different modules work. So, I am working on a project on which I wanna achieve an accordion-like style for a page, in which a table is shown when I click a panel button. The HTML code that creates(dynamically from a database) the div elements I modify is posted below.The problem is that in this panel, any number of tables can be shown,while I need to only have one opened at a time,so when one opens,the one opened before it should close.Any ideas how I can achieve this functionality?(I assume the error is because the showDB variable is local to each table scope, but I don't know how to work around it.) Thanks!' `
<div ng-repeat="(key, value) in data.services">
<div ng-show="showSection(key)" class="top_panel-section">
<button class="btn top_btn btn-header" type="button" name="showDB"
ng-click="showDB=!showDB">{{key}}</button>
<table ng-show="showDB"
class="n-table toptable table-responsive n-table-standard n-table-striped n-table-hover">
<thead class="n-table-thead">
<tr>
<th width="70%">VM Name</th>
<th width="30%">Status</th>
</tr>
</thead>
<tbody class="n-table-body">
<tr ng-repeat="vm in value.vms">
<td width="76%">{{vm.vm}}</td>
<td width="24%" ng-style="getStatusStyle(vm.status)">
{{vm.status}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Yes, you should remove that local showDB variable to achieve what you need.
You can easily replace it with a $scope.activeKey and evaluating it by the
<button ... name="showDB" ng-click="activateKey(key)">{{key}}</button>
And in your controller:
$scope.activeKey = null;
$scope.activateKey = function (keyToBeActivated) {
$scope.activeKey = keyToBeActivated;
}
Now you can reach that exclusivity by checking:
<table ng-show="activeKey === key" ... >
Using table $index as unique field: (available from ng-repeat)
<button ... name="showDB" ng-click="activateKey($index)">{{key}}</button>
And
<table ng-show="activeKey === $index" ... >

Repeating a set of <td>s in the same table row using AngularJS

I want to create a table that, in its header, contains the names of each player for two teams in each . The scope has a variable teams which is a list of Team objects, each one having list of Player objects as an attribute.
This is turning out to be way harder than I expected.
<table>
<thead>
<tr>
<div ng-repeat="team in teams">
<th ng-repeat="player in team.players">{[ player.name ]}</th>
<th>Partial Score</th>
<th>Total Score</th>
</div>
</tr>
</thead>
</table>
is the easiest thing I have in mind - but this doesn't work. can't be placed inside a according to W3C (from what I understand), so the browser just takes the div and places it outside the table.
I've tried directives as well - but these don't help. This is an example of my directive file.
<th ng-repeat="player in team.players">{[ player.name ]}</th>
<th>Partial Score</th>
<th>Total Score</th>
For example, if I have a <player-initials> directive with replace: 'false', the browser expels the non-<th> element out of the table. Setting replace: 'true', fixes that, but then I get an error because there's more than one root element in the directive. I can't wrap the elements in the directive with anything because that would result in invalid HTML (as above).
I've tried all combinations of element and attribute directives and replace, nothing gives me what I want. Any help?
Created a fiddle here.
Hope this is what you are looking for, if not let me know the format that you are looking for. Your HTML should look something like below.
<table ng-repeat="team in teams">
<tr>
<td colspan="3">
{{team.name}}
</td>
</tr>
<tr>
<td>Player Name</td>
<td>Partial Score</td>
<td>Total Score</td>
</tr>
<tr ng-repeat="player in team.players">
<td>{{player.name}}</td>
<td>{{player.PScore}}</td>
<td>{{player.TScore}}</td>
</tr>
</table>
You should add a method to your scope that do the logic for you.
Something like this should work:
$scope.getAllPlayers = function() {
var players = [];
this.teams.forEach(function(team){
players = players.concat(team.players);
});
return players;
}
Then in your dom:
<table>
<thead>
<tr>
<th ng-repeat="player in getAllPlayers()">{{ player.name }}</th>
<th>Partial Score</th>
<th>Total Score</th>
</tr>
</thead>
</table>
I'm not using Angular so I may be wrong, but I'm pretty sure this is the way to go. This kind of logic have to be in your controller, as simple is a nested loop.
EDIT: Referring to the comments, you could make a function that return your header cells the way you want them
$scope.getHeaderCells = function() {
var cells = [];
this.teams.forEach(function(team){
cells = cells.concat(team.players.map(function(player){
return { team: team, value: player.name };
})).concat([
{team: team, value: 'Partial Score'},
{team: team, value: 'Total Score'}
]);
});
console.log(cells);
return cells;
}
with
<th ng-repeat="cell in getHeaderCells()">{{ cell.value }}</th>
here is a fiddle
I figured it out using the ng-repeat-start and ng-repeat-end directives. I really didn't want to write functions to generate HTML for me, because that's why I switched to Angular in the first place.
Here's a screenshot: http://i.imgur.com/e5LBvQB.png.
This is the (stripped-down to relevant part) code just for the header, everything else is similar. The only 'hacky' part I don't like is the ng-show attributes for B and T to reverse it properly, but it works for me right now. I think I can get clean it up with directives.
<table class="table table-condensed table-striped table-hover table-responsive">
<thead>
<tr>
<th ng-repeat-start="team in game.getTeams()" ng-hide="true"></th>
<th ng-repeat="player in team.getPlayers()" ng-class="$parent.$first && 'text-info' || 'text-danger'">
<u>
{[ player.name | truncate ]}
</u>
</th>
<th ng-repeat-end ng-show="$first">
#
</th>
</tr>
</thead>
</table>

Categories