how to get the result of two controller on ng-repeat - javascript

I want to get the values of the two object in thesame ng-repeat
$http.get('/api/PreviewPayroll').success(function (data){
//alert(data[0].empID);
$scope.allowance = data;
});
$http.get('/api/Deduction').success(function (data){
//alert(data[0].empID);
$scope.Deduction = data;
});
<tr ng-repeat="item in allowance && ng-repeat="value in Deduction">
<td>{{ item.empID }}</td>
<td>{{ value.empID }}</td>
</tr>
how can I get the two scope object on thesame ng-repeat

So you will want to combine the data.
You can use $q.all(promises):
var promise1 = $http.get('/api/PreviewPayroll');
var promise2 = $http.get('/api/Deduction');
$q.all([promise1, promise2]).then(function (results) {
var allowances = results[0];
var deductions = results[1];
var combinedList = /* some combination logic */;
});
By using $q.all() you are ensuring you have both lists of data before trying to combine anything. You can easily play around with this to get the desired effect. For example, if you don't care if the other list isn't available.
Then you can use the ng-repeat in order to iterate over that new combined list:
<tr ng-repeat="item in combinedList">
<td>{{ item.allowance.empID }}</td>
<td>{{ item.deduction.empID }}</td>
</tr>
The sub properties allowance and deduction are based on your combined list.
However
It is in my honest opinion that, the server side gives you the data in the format you need to display it in. (i.e. the business logic remains server side in a controlled environment). I believe the view should only deal with view logic, like button actions etc..
But this is my opinion, and is what I find easiest.
Another note
I prefer to also keep the view logic in the JavaScript, hence why I combine the data there. Rather than trying to do some overly complicated angular expression in the HTML.

You could either have a nested ng-repeat and also combine the two objects into one.
<table>
<tbody ng-repeat="row in mainCombinedObject">
<tr>
<th>{{row.empID}}</th>
</tr>
<tr ng-repeat="sub in row.subObject">
<td>{{sub.empID}}</td>
</tr>
</tbody>
</table>

Combine $scope.allowance and $scope.Deduction to one list of objects "combined" then do your ng-repeat:
<tr ng-repeat="c in combined">
<td>{{ c.someField }}</td>
<td>{{ c.someOtherField }}</td>
</tr>

You can't do that in such way! If your allowance and Deduction have the same size you have to mix them in the collection like this:
var array = [
{ allowance: value1, Deduction: value2},
{ allowance: value3, Deduction: value4},
...
];
and them use it in the view:
<tr ng-repeat="item in array">
<td>{{ item.allowance.empID }}</td>
<td>{{ item.Deduction.empID }}</td>
</tr>

Related

Single query per pagination? datatable.js laravel

Currently I have a table called tblOrders
with the query like this
public function getIndex()
{
$cart = Cart::orderby('cart_date','DESC')
->orderby('cart_no','DESC')
->select('id','cart_no','client_id','cart_title')->limit(1000)->get();
return View::make('_admin.orders.orders', compact('cart'));
}
on my blade file I have this datatable.js
<table id="table-order" class="parennt-table uk-table-hover">
<thead>
<tr>
<th>id</th>
<th>cart_no</th>
<th>cart_title</th>
<th>cart_date</th>
</tr>
</thead>
<tbody>
#if(count($orderData))
#foreach ($orderData as $field)
<tr>
<td>{{ $field->id }}</td>
<td>{{ $field->cart_no }}</td>
<td>{{ $field->cart_title }}</td>
<td>{{ date('M j, Y',strtotime($field->cart_date)) }}</td>
</tr>
#endforeach
#endif
</tbody>
and my js like this
<script>
oTable = $('#table-order').DataTable({
"order": [[ 0, 'desc' ]]
});
</script>
This datatable loads 8k rows. but needed to limit it by 1000 rows
How can I load only 20 rows per page? and query the next 1 when user tries to click specific pagination
You should use pagination, the first parameter passed to the paginate() function is the number of results returned.
public function getIndex()
{
$cart = Cart::orderby('cart_date','DESC')
->orderby('cart_no','DESC')
->select('id','cart_no','client_id','cart_title')
->paginate(50);
return View::make('_admin.orders.orders', compact('cart'));
}
However, I don't suggest you to use such a high number as 1000 but use more reasonable numbers to reduce the page loading and rendering time.
Anyway, using DataTables I suggest you to install this package yajra/laravel-datatables

How can I add loading ONLY to the clicked button in vuejs?

There is a table which loops and outputs the data which comes from API. I have added a button inside the table. When you click it, it should send the id of the clicked button and till it recieves the data of the function which needs to be printed, it should be in loading. Here is my code.
<table id="customers">
<tr>
<th>{{$t('message.numberReport')}}</th>
<th>{{$t('message.periodFrom')}}</th>
<th>{{$t('message.periodTo')}}</th>
<th>{{$t('message.printButton')}}</th>
</tr>
<tr v-for="(item,index) in getReportInfo" :key="index">
<td>{{ item.id }}</td>
<td>{{ item.periodFrom }}</td>
<td>{{ item.periodTo }}</td>
<td>
<v-btn
class="primary"
:loading="loading"
:disabled="loading"
#click="fetchGetReportDetailed(item)"
>{{ $t('message.printButton')}}</v-btn>
</td>
</tr>
</table>
But when I clicked the particular button, all the buttons are getting in loaded mode. How do I fix it? Any suggestion would be deeply appreciated.here is the visual example
Using index of item in list.
You can register a new variable in your data for example indexClicked .
data () {
return {
// Some predefined value, 0 isn't good because index can be 0.
indexClicked: undefined // Some predefined value
}
}
And when you click at button you can send index value:
<td>
<v-btn class="primary"
:loading="loading && indexClicked === index"
:disabled="loading && indexClicked === index"
#click="fetchGetReportDetailed(item, index)">
{{ $t('message.printButton') }}
</v-btn>
</td>
And in your fetchGetReportDetailed(item, index) method you need to assign index to this.indexClicked like:
fetchGetReportDetailed (item, index) {
// Your code
this.indexClicked = index;
}
This should work. But if you need more information please provide more code.
Note if you have a problem with multiple conditions in :disable you can create a method which will return true or false depends on condition loading && this.indexClicked === index.
Good luck!
You're using a single data property for all rows, so in mounted hook add a property called loading to each row like :
mounted(){
this.getReportInfo=this.getReportInfo.map(rep=>{
rep.loading=false;
return rep;
});
}
and the template do:
<tr v-for="(item,index) in getReportInfo" :key="index">
<td>{{ item.id }}</td>
<td>{{ item.periodFrom }}</td>
<td>{{ item.periodTo }}</td>
<td><v-btn class="primary" :loading="item.loading" :disabled="loading" #click="fetchGetReportDetailed(item,index)" >{{ $t('message.printButton')}}</v-btn></td>
</tr>
in fetchGetReportDetailed method :
fetchGetReportDetailed(item,index){
....
this.getReportInfo[index].loading=true;
this.$set(this.getReportInfo,index,this.getReportInfo[index])
}
You could separate the tr that is displaying the data into its own state-full component and call the function from within the component.
This way the state of loading for each item in the array will be local to its own component.

How to pass variable from twig to js?

Code prints out tasks information. I want to pass tasks array to JS. How could I do that? Some of my twig code:
<div>
{% for task in tasks %}
<tr>
<td id>{{ task.Id }}</td>
<td>{{ task.Status }}</td>
<td>{{ task.Name }}</td>
<td>{{ task.Description }}</td>
<td>{{ task.Category }}</td>
<td>{{ task.Author }}</td>
<td>{{ task.CreationDate|date("m/d/Y") }}</td>
<td><a id="myLink" href="/edit/{{ task.ID }}" > Edit </a></td>
<td><a id="myLink" href="/delete/{{ task.ID }}" >Delete</a></td>
<?php echo 2+2; ?> </tr>
{% endfor %}
</table>
</div>
I want to pass array to this js class:
$(function(){
$('#calendar').fullCalendar({
});
});
You can serialize the array in json format: {{ tasks | json_encode() }}.
If your javascript is inside a <script> element of the twig template, you can just do: var data = {{ tasks | json_encode() }}.
Otherwise, you can put the serialized array somewhere in the twig template as an element's attribute:
<div id="data-element" data-tasks="{{ tasks | json_encode() }}">.
Then just get the data with
var jsonString = $('#data-element').data('tasks');
var data = JSON.parse(jsonString);
First of all , you need to know that there are a big deference between PHP arrays and Javascript arrays.
you need to convert your array to a common understood format that both PHP and Javascript can understand , which is JSON .
so I will assume that you are sending your tasks from your controller to twig as a json format, then you can set your javascript variable as follows :
<script>
var tasks = '{{ tasks }}';
var tasksObj = JSON.parse(tasks); // to convert json into a javascript object
</script>

Angularjs -Updating individual values in ng-repeat from outside its scope using "this" keyword

I am trying to update quantity number of individual items in a table whenever the user clicks the item in another table.
For example, I have list of all items in Table A
<tr ng-repeat="item in items">
<td>{{item.fid}}</td>
<td{{ item.fname }}</td>
<td>{{ item.calorie }}</td>
<td>{{ item.protein }}</td>
<td>{{ item.carb }}</td>
<td>{{ item.fat }}</td>
<td><button ng-click=additem(values)>Add</button>
<tr>
Now when the user clicks this Add button, the selected item gets added to another table (Table B).
I have disabled duplicates in Table B and want that if the user is repeatedly adding same item then the quantity of the item in Table B should increase.
Table B
<tr ng-repeat="sitem in sitems>
<td>{{sitem.fname}}</td>
<td>{{sitem.calorie}}</td>
<td>{{sitem.protein}}</td>
<td>{{sitem.carb}}</td>
<td>{{sitem.fat}}</td>
<td>*</td>
<td><button ng-click="removeItem(values)">Remove</button></td>
</tr>
is the one where i want the increased quantity to be shown.
I have tried using "this" keyword but didn't worked, I am new to angular so i don't know what all are my options and got mixed up.
You have to keep track of two separate array to accomplish this.
This is the code snippet: `
$scope.additem = function(item) {
var index = $scope.sitems.indexOf(item);
if (index === -1) {
item.quantity = 1;
$scope.sitems.push(item);
return;
}
item.quantity++;
$scope.sitems[index] = item;
};
`
Complete Working fiddle: https://jsfiddle.net/nbakliwal18/4kbo7Lfo/2/
Also you check for quantity before adding.
You can simply pass item to the function addItem() :
<td><button ng-click=addItem(item)>Add</button>
and push this item to your array sitems in your function :
$scope.addItem = function(item) {
$scope.sitems.push(item);
}
A workaround for the duplicates in ng-repeat is to add track by $index to it :
<tr ng-repeat="sitem in sitems track by $index">
Update 1:
Updated my answer with working example in Plunker
Update 2:
Here is an example with lodash for quantity Plunker

AngularJS sorting by time difference

I want to enable sorting by each of my table fields. I have one column which shows how many minutes it took to work on project, but sorting by this field doesn't work properly.
<table>
<th >Company</th>
<th>Time difference<th />
<tr ng-repeat="task in tasks | orderBy:sortBy">
<td >{[{ task.company_name }]}</td>
<td >{[{ timediff(task.time_start,task.time_stop) }]}</td>
</tr>
</table>
timediff function:
$scope.timediff = function(start, end){
var start = moment(start);
var end = moment(end);
var diff = end.diff(start,'minutes',true);
return (diff/60).toPrecision(3);
};
Plunker: http://plnkr.co/edit/vdkfNkgpdLUp9RgZ1IvO?p=preview
Simple fix, just need to assign the function to a parameter
<tr>
<th>Company</th>
<th>Time difference</th>
</tr>
<tr ng-repeat="task in tasks | orderBy:sortBy">
<td>{{ task.company_name }}</td>
<td>{{ task.timediff = timediff(task.time_start,task.time_stop) }}</td>
</tr>
Here is an updated plunker showing this as well as adding a reverse sort.
There is a simpler way for the custom function to work. I edited the dataset a bit to make the switch between "Company" and "Time difference" a bit more clear.
Option 1 (DEMO):
If the property names don't change you can do the following :
$scope.timediff = function(task){
var start = moment(task.time_start);
var end = moment(task.time_stop);
var diff = end.diff(start,'minutes',true);
return (diff/60).toPrecision(3);
};
And in your html assign the function to your sortBy variable:
<th >Company</th>
<th>Time difference</th>
<tr ng-repeat="task in tasks | orderBy:sortBy">
<td >{{ task.company_name }}</td>
<td >{{ timediff(task)}}</td>
</tr>
Angular automatically passes the current item into the function defined in orderBy.
Option 2 (more flexible) (DEMO):
If you want to define the property names on the fly you can return another function:
$scope.timediff = function(name1, name2){
return function(item) {
var start = moment(item[name1]);
var end = moment(item[name2]);
var diff = end.diff(start,'minutes',true);
return (diff/60).toPrecision(3);
}
};
And give it the two property names:
<th >Company</th>
<th>Time difference</th>
<tr ng-repeat="task in tasks | orderBy:sortBy">
<td >{{ task.company_name }}</td>
<td >{{ timediff('time_start', 'time_stop')(task)}}</td>
</tr>

Categories

Resources