I am building a simple contact database with Laravel and a MySQL database. I have a basic HTML file with a data table that list a series of records. I would like to make it so that when I click on a row, I go to a page based on the ID number of the record in the row clicked.
I have the table populated using a #foreach loop as such:
<tbody>
#foreach ($people as $person)
<tr>
<td>
<a>{!! link_to_action('ContactController#show', $person->id, $person->id) !!}</a>
</td>
<td>{{ $person->name_first }}</td>
<td>{{ $person->name_middle }}</td>
<td>{{ $person->name_last }}</td>
</tr>
#endforeach
</tbody>
The controller (ContactController) shows this:
public function show($id)
{
$person = Contact::findOrFail($id);
return view('contacts.show', compact('person'));
}
Now, I have a JavaScript script on the page:
<script type="text/javascript">
$(document).ready(function() {
$('#contacts').dataTable();
$('#contacts tbody').on('click', 'tr', function () {
var name = $('td', this).eq(1).text();
alert( 'You clicked on '+name+'\'s row' );
window.location="";
} );
} );
</script>
I assume I only need to insert the proper link in:
window.location="";
How do I write the link? I tried writing a number of variations with the Laravel syntax, where I need to access a route in my ContactController that would go to contacts/{id}. I tried:
window.location="{{URL::to('contacts', $person->id)}}";
That doesn't work. Please let me know what link to use in order to go to contacts/1 or contacts2, for example.
try this.
$('#contacts tbody').on('click', 'tr', function () {
var name = $('td', this).eq(1).text();
var link = $('td', this).eq(0).find('a');
alert('You clicked on ' + name + '\'s row');
window.location=link.attr('href');
});
And the show method only accepts one argument.
<td>
{!! link_to_action('ContactController#show', $person->id) !!}
</td>
And no need to wrap it in "a" tags
Add your link to a data attribute on your tr element and then use it in your JavaScript.
HTML:
<tbody>
#foreach ($people as $person)
<tr data-link='{{ action('ContactController#show', $person->id) }}'>
<td>
<a>{!! link_to_action('ContactController#show', $person->id, $person->id) !!}</a>
</td>
<td>{{ $person->name_first }}</td>
<td>{{ $person->name_middle }}</td>
<td>{{ $person->name_last }}</td>
</tr>
#endforeach
</tbody>
JavaScript:
$('#contacts tbody').on('click', 'tr', function () {
var name = $('td', this).eq(1).text();
alert( 'You clicked on '+name+'\'s row' );
window.location = this.getAttribute('data-link');
} );
Related
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
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.
In my webpage I am populating a table using handlebars and getting the values from a db:
<table>
<tbody id="myDiv">
{{# each alarms}}
<tr class="row100 body">
<td class="cell100 column1">{{ this.alm_id }}</td>
<td class="cell100 column2>{{ this.message }}</td>
<td class="cell100 column3">{{ this.level }}</td>
</tr>
{{/each}}
</tbody>
</table>
Now I want that rows to be clickable and to open a particular popup depending on the row (there will be a description of that row).
So I wrote this:
<script>
var modal_exp = document.getElementById('myModal_explanatory');
var btn_exp = document.getElementById("myBtn_exp");
var span_exp = document.getElementById("close_exp");
btn_exp.onclick = function() { modal_exp.style.display = "block"; }
span_exp.onclick = function() { modal_exp.style.display = "none"; }
window.onclick = function(event) {
if (event.target == modal_exp) { modal_exp.style.display = "none"; }
}
</script>
The popup works well when called outside the table.
Inside the table it doesn't work and the problem is that I'm assigning the same id to every row and it doesn't know which one is referring to.
I have no idea how to solve this.
The idea is to have a different id for every row (that can be achieved using handlebars, e.g. id="myBtn-{{this.id}}" but then I don't understand how to assign it to my bin_exp variable inside the script.
An approach using classes would work much better over IDs. Classes are a great way to apply an identifier to similar elements. In this case you need a way to apply a click event to multiple btn-exp.
To pass the data to the element, leverage to data attribute on the element. You can pass what ever data from handle bars you need into the attribute an later access in JavaScript.
<table>
<tbody id="myDiv">
{{# each alarms}}
<tr class="row100 body">
<td class="cell100 column1">
<!-- Class will be used to select all .btn_exp and from their events you can access the unique data -->
<a href="#" class="btn_exp" data-alm-id="{{this.alm_id}}">
{{ this.alm_id }}
</a>
</td>
<td class="cell100 column2>{{ this.message }}</td>
<td class="cell100 column3">{{ this.level }}</td>
</tr>
{{/each}}
</tbody>
</table>
var modal_exp = document.getElementById('myModal_explanatory');
var btn_exp = document.querySelectorAll('.btn_exp'); // This returns a NodeList of the .btn_exp objects
var span_exp = document.getElementById("close_exp");
span_exp.onclick = function() { modal_exp.style.display = "none"; }
btn_exp.forEach(function(button) {
button.addEventListener('click', function(event) {
// Through the event object you can get the unique instance of .btn_exp that you clicked
var button = event.currentTarget
modal_exp.style.display = "block";
// If you wanted to get the data-alm-id value for this specific button you can access it like this
var button_alm_id = button.dataset.almId // dashes are converted to Camel case
// ... Do what ever you want with this value
});
});
For more info on querySelector() and querySelectorAll() checkout the MDN here https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
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
I have following lines of code in my AngularJS project.
<div ng-show="update">
<table border="1">
<tr ng-repeat="x in names">
<td>{{ x.uname}}</td>
<td>{{ x.upass}}</td>
<td><button ng-model="index" ng-click="show()"
ng-value="{{x.index}}">Edit</button></td>
</tr>
</table>
When Particular button is clicked I want to retrieve that button label.
For that I have written code in Show function:
var v = $scope.index;
alert(v);
But alert box is displaying "Undefined" when i click on button.
Please suggest me where I am wrong??
Thanks in advance
What about providing your value as an argument to the onclick function ?
<div ng-show="update">
<table border="1">
<tr ng-repeat="x in names">
<td>{{ x.uname}}</td>
<td>{{ x.upass}}</td>
<td><button ng-click="show(x.index)">Edit</button></td>
</tr>
</table>
and then
function show(id){
alert(id);
}
This should works. Also ng-model does not work on button.
under ng-click = show(item) - this gives the particular item object.
function show(obj){ console.log(obj)}
this function give the particular clicked obj from view.
ng-model doesn't work on button.
You can pass the index of the repeat iteration to the show method like this:
<button ng-click="show($index)" ...
and use it like this:
function show(i){
var v = names[i];
alert(v);
}
You can see it in action here: PLNKR DEMO
NOTE: if you are passing the index to the backend service the index may not match up with the actual array if you are using a filter in your view to alter/reduce the ng-repeat expression
Another option as pointed out by #Grundy is to just pass the object back, which saves you the step of having to access it from the array... (note: this is the suggested best practice)
I am assuming that you want the button label that you have clicked on and the index of it in the list provided. Here is what you can do.
<div ng-repeat="buttonId in testdata2">
<button ng-bind="buttonId" ng-click="clickedMe(buttonId, $index)"></button>
</div>
$scope.clickedMe = function(buttonId, index) {
console.log(buttonId + " - " + index);
};
Have your files in local and run them.