I am trying to get table data when the user clicks on the text inside element. I have tried number of java script but I cant get the value to be send back to the controller for further processing. I would really appreciate if you can help me out. I have added necessary code for you to see if I am doing something wrong.
<div class="box-content">
<table id="suppliertable" class="table table-striped table-bordered bootstrap-datatable datatable">
<thead>
<tr>
<th>Supplier</th>
<th>Open Range</th>
<th>Fill Content</th>
<th>Total Match</th>
</tr>
</thead>
<tbody>
<?php foreach($present_all_suppliers as $v): ?>
<tr>
<td class="center" style="color:#0c595b;"><?php echo $v->supplierCompany;?> </a> </td>
<td class="center">70%</td>
<td class="center">12%</td>
<td class="center">82%</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
Java Script:
document.getElementById ( "tdid" ).textContent
var tdElem = document.getElementById ( "tdid" );
var tdText = tdElem.innerText | tdElem.textContent;
This is going to require some fancy ajax and a javascript enclosure. Hopefully this example will help.
http://jsfiddle.net/qpe2wrmt/1/
function addEventHandler(elem,eventType,handler){
if (elem.addEventListener)
elem.addEventListener(eventType,handler,false);
else if (elem.attachEvent)
elem.attachEvent ('on'+eventType,handler);
}
var items = document.getElementsByClassName("clickable");
i = items.length;
while(i--){
(function(item){
addEventHandler(item,"click",function(){
// make your ajax call here
window.alert("clicked on a thing: "+item.innerHTML);
});
})(items[i]);
}
1) Add a 'clickable' class to each td you want to be cliackable
2) Loop through all clickable items by classname and assign an event handler to each.
3) Make an XHR request when clicked on.
You need to pass the data back to the controller from Javascript. That means that when the user clicks on the <td> in question an AJAX request must be sent to the appropriate controller and the controller can then execute some server action or return some data that would be used by the AJAX callback function.
Here is an example:
http://www.w3schools.com/php/php_ajax_php.asp
This shows how to use AJAX and PHP to make dynamic changes to the HTML DOM objects.
Here is another question on stackoverflow about onclick and AJAX and PHP:
Call a PHP function after onClick HTML event
What you need to learn is AJAX and how to build your application to use it if you want to make the page look and feel more modern (HTML5).
Related
I have a problem with AlpineJS in my complicated app, and I'm finding it very difficult to replicate under a simplified example. This may well mean that it's a bug in Alpine, but I'll ask here for help on the off-chance anyway. I've tried to reduce the code below to only the bare essentials that are necessary to explain the problem, and doing so may have lead to some typos. Therefore please excuse me in advance for any errors that are not related to the problem itself.
I'm using Livewire to synch data between my PHP classes and my AlpineJS front-end. The two variables that are relevant in the PHP class are:
public $colOrder; // users are able to "re-order" columns on their table-view. This preference is saved into their profile and stored in this variable as a 1D array of the column-IDs
public $datasourceData; // contains a 2D data that is pulled from a database with: Model->get()->toArray(); [0 => ['col1'=>'data1,1', 'col2'=>'data1,2'], 1 => ['col1'=>'data2,1', 'col2'=>'data2,2']];
These arrays are then entangled with Alpine variables, and the template is generated from those arrays of data as follows. Ostensibly, this template works fine:
<div x-data="{
eColOrder: #entangle('colOrder').defer,
eData: #entangle('datasourceData').defer
}">
<table class="table" x-cloak>
<thead>
<tr>
<template x-for="(col, ix) in eColOrder" :key="'th-'+ix">
<th x-text="col"></th>
</template>
</tr>
</thead>
<tbody>
<template x-if="eData.length==0">
<tr>
<td :colspan="eColOrder.length" style="padding: 1em">No data found</td>
</tr>
</template>
<template x-if="eData.length>0">
<template x-for="(rec, ix) in eData" :key="'row-'+ix">
<tr>
<td class="action"></td>
<template x-for="(col, pos) in eColOrder" :key="'td-'+ix+'-'+pos">
<td x-text="rec[col]"></td> <!-- I also tried `eData[ix][col]`, but it produced errors in the browser console, even though the on-screen display was fine -->
</template>
</tr>
</template>
</template>
</tbody>
</table>
In this screen-shot, you can see that the user's search (in the top-row) has produced a tabulated grid of data below. Happy days.
The problem arises when the user re-submits a different search. They do so by updating the search fields, and pressing the "search" button again. This re-submits the search (through a Livewire JSON call), refreshing the $datasourceData array with new data, entangling itself with the eData variable in Alpine, and producing the following result:
What appears to be happening, is that the results of the new search are correctly pulled through. But for whatever reason, Alpine hasn't cleared the screen from the last set of search-results. It's interesting that only the data-level of the HTML table is corrupted (that is to say, the <td> cells). Note that the <th> cells have (correctly) not been duplicated above the right-hand-half of the new table.
I've debugged and checked that the data returned from the Eloquent models is correct, and that the structure of the data in the entangled JavaScript variable eData is also correct. This problem is not data-related, it's the rendering that's at fault.
My gut-feel is that this is an Alpine bug, but I haven't been able to prove it yet.
My problem stops there. However, in an attempt to replicate the issue and narrow down the cause of the issue, what I've done is to create a simplified Livewire/Blade/Alpine page. Strictly speaking, I wasn't able to replicate the problem there either directly, but I did (accidentally) manage to replicate a similar output when I entered a deliberate "bug" into my code.
Take the following PHP/Livewire component:
<?php
namespace App\Business\Tbd;
use Livewire\Component;
class StartLw extends Component
{
public array $data = [];
public array $headings = [];
public int $count = 0;
public function mount() {
for ($i=1; $i <= 6; $i++) {
$this->headings[] = "col{$i}";
}
$this->data = [];
}
public function formSubmit() {
$src = 1;
$this->data = [];
for ($i=0; $i < 10; $i++) {
$this->data[$i] = [];
for ($y=1; $y <= 6; $y++) {
$this->data[$i]["col{$y}"] = "source {$src} ({$i},{$y})";
}
}
$this->count++;
}
public function relatedToButSeparateFromForm() {
$src = 2;
$this->data = [];
for ($i=0; $i < 4; $i++) {
$this->data[$i] = [];
for ($y=1; $y <= 6; $y++) {
$this->data[$i]["col{$y}"] = "source {$src} ({$i},{$y})";
}
}
$this->count++;
}
public function render()
{
return view('components.tbd.lw-start-lw')
->layout('layouts.tbd.lw');
}
}
And this cut-down HTML to render the page:
<div class="container" x-data="{
eData: #entangle('data').defer,
eHeadings: #entangle('headings').defer
}">
<div class="row">
<div class="col"><p>{{ $count }}</p></div>
</div>
<div class="row">
<div class="col">
<form method="post" wire:submit.prevent="formSubmit">
<p>
<button type="submit">Load data source 1</button>
<button type="button" wire:click="relatedToButSeparateFromForm">Load data source 2</button>
</p>
</form>
</div>
</div>
<div class="row">
<div class="col">
<table>
<thead>
<tr>
<template x-for="hd in eHeadings">
<th x-text="hd" style="padding: 0.5em; background-color:rgb(220,220,230); border: 1px solid rgb(210,210,230)"></th>
</template>
</tr>
</thead>
<tbody>
<template x-for="(row, ix) in eData" :key="ix">
<tr>
<template x-for="(col, pos) in eHeadings" :key="'td-'+ix+'-'+pos">
<td x-text="row[col]" :class="id" style="padding: 0.5em; background-color:rgb(240,240,255); border: 1px solid rgb(210,210,230)"></td>
</template>
</tr>
</template>
</tbody>
</table>
</div>
</div>
</div>
Note the deliberate error! On the <td> element, :class="id" should really say :class="col". Now if I take out the error, the page works as I would expect it to. But with the error re-introduced into the code (together with a bunch of error messages in the browser console saying: Uncaught ReferenceError: id is not defined), after toggling the two buttons back and forth a bit, I get this:
As I think you'll agree, that picture is spookily reminiscent of the situation I get in my real world application (except that in the real-world-app, I don't end up with any errors in the browser's console).
This leads me to the strong belief that there is a silent bug being triggered somewhere in the Alpine engine which triggers the same net result. I will go and log this on their GitHub support pages too, but I have always found the Stack community to be super useful in the past too. I hope that someone out there is able to help validate that I'm not missing anything obvious!
Posted the issue on the Alpine bug-report pages, and got the response I wanted. See >> https://github.com/alpinejs/alpine/discussions/2523#discussioncomment-1860670
Apparently, it's not an Alpine issue at all. The problem is that Livewire is treading on Alpine's toes. Livewire "watches" the DOM for updates, and it seems that it's then failing to release (or clean-up, or whatever the correct term is) certain subsections of the DOM as Alpine refreshes it with the new load of data. This explains why earlier incarnations of the DOM are hanging about for longer than they are required.
Resolution is to force Livewire to not-watch the DOM for differences by using the wire:ignore directive. This can be put on the <table> itself, or any parent element thereof. In my example I put it on the immediately encapsulating <div>:
<div class="whoopsie" wire:ignore>
<table>
<!-- etc -->
<tbody>
<template x-for="(col, pos) in eColOrder" :key="'td-'+ix+'-'+pos">
<td x-data="row[col]"></td>
</template>
</tbody>
<!-- etc -->
</table>
</div>
this is what it shows on clicking tab one time 2nd time I click it loads last two file .15 and .17 again alltogetherthis is shown in console when I inspect even if I have not clicked on tab.And displays this data in browser when I click tab. This should not be shown whn console is clicked while inspectin page. Data only to be loaded only when I click tab.
Object {type: "FeatureCollection", metadata: Object, features:Array[11], bbox: Array[6]}bbox: Array[6]features: Array[11]metadata: Objecttype: "FeatureCollection"proto: Object
here is my code..
<body ng-controller="CountryCtrl">
<div ng-app ng-init="tab=1">
<div class="cb" ng-click="tab = 1">tab 1</div>
<div class="cb" ng-click="tab = 2">tab 2</div>
<div ng-show="tab == 1">
<p>hellloollllllllllllo</p>
</div>
<div ng-show="tab == 2">
<h2>Angular.js JSON Fetching Example</h2>
<table border=1>
<tr>
<th>type</th>
<th>properties_mag</th>
<th>properties_place</th>
<th>properties_time</th>
<th>properties_upated</th>
<th>properties_tz</th>
</tr>
<tr ng-repeat="type in country ">
<td>{{type.type}}</td>
<td>{{type.properties.mag}} </td>
<td> {{type.properties.place}} </td>
<td> {{type.properties.time}} </td>
<td> {{type.properties.updated}} </td>
<td> {{type.properties.tz}} </td>
<tr ng-repeat="cor in features.geometry.coordinates ">
<td> {{cor}} </td>
</tr>
</table>
</div>
this is controller function.....
var countryApp = angular.module('countryApp',[]);
countryApp.controller('CountryCtrl', function ($scope, $http){
$http.get('http:/4.5_day.geojson').success(function(data) {
console.log(data);
$scope.country = data.features;
$scope.coor=data.features.geometry.coordinates;
console.log($scope.country);
});
});
I would suggest that you simply call the function that loads the JSON data when clicking the second tab using ng-click. This way you will not get it loaded unless the tab is clicked.
You could change:
<div class="cb" ng-click="tab = 2">tab 2</div>
To:
<div class="cb" ng-click="switchTabAndLoadData()">tab 2</div>
And defined the function in your controller to update the tab variable and load the JSON.
You are calling the $http service directly in your controller that's why the data is loaded up front. Try this:
var countryApp = angular.module('countryApp',[]);
countryApp.controller('CountryCtrl', function ($scope, $http){
var loadData = function(){
$http.get('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_day.geojson').success(function(data) {
console.log(data);
$scope.country = data.features;
$scope.coor=data.features.geometry.coordinates;
console.log($scope.country);
});
}
$scope.switchTabAndLoadData = function(){
$scope.tab=2;
if(angular.isUndefined($scope.country) || angular.isUndefined($scope.coor)){
loadData();
}
}
});
Make sure to also apply the HTML change I previously suggested and it should be fine.
You problem lies elsewhere, had you checked the console you would have seen that angular gives an error on your assignment of variables for $scope.coor since you are trying to assign properies of an object in an array of object.
Check this pen for a solution: http://codepen.io/anon/pen/BjXGGJ
You can then adjust the HTML do your needs.
I have been using angular js to develope web applications and i am quite fan of it. Just starting my hands on laravel 5 to learn something new. I am trying to find angular's ng-click replacement in laravel for blelow situation.
I am using simple html (no php form tags) to insert some data and display it in php blade templete using blade's #foreach control sturcture like below
<table class="table table-bordered table-striped table-hover">
<tr>
<th>S.No</th>
<th>Name of value</th>
<th></th>
</tr>
#foreach( $values as $index=>$value)
<tr>
<td>{{$index +1}}</td>
<td>{{$value->value_name}}</td>
<td><button class="btn btn-success btn-sm" data-toggle="modal" data-target="#editValueModal" onclick="<?php $selectedValue = $value ?>">Edit</button></td>
</tr>
#endforeach
</table>
data is being displayed properly. As you can see on click "edit" button i open a popup . Now here the problem comes. I am trying to display the value_name in the popup whose edit button is being clicked. i tried to use html's onclick function to set a variable for the correspoiding $value object but it is always setting the last $value of loop in the variable $selectedValue.
Can some please tell me the way i can do it.
Use this: {{--*/ $abc = 0 /*--}}
I have table in which data comes from the database.and I have the form on the same page which insert the data in the table.but when I insert data using $.ajax , it inserts record in database , but after reloading table in same function is not working, means it doesn't reload the table.
below is my code.
HTML
<div class="col-lg-8" id="value_table">
<div class="panel-body">
<div class="table-responsive">
<?php
$q=$db->query('select attr_val_id,attr_val,sortorder,status from db_attribute_value where attr_id="'.$attr_id.'"' );
?>
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered" id="example">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Edit/Delete</th>
</tr>
</thead>
<tbody>
<?php $c=1; while($r=$q->fetch_assoc()){?>
<tr class=" gradeX">
<td><?php echo $c; ?></td>
<td><?php echo $r['attr_val']; ?></td>
<td><a href="add_attribute_val.php?id=<?php echo $r['attr_val_id']; ?>&attr_id=<?php echo #$r['attr_id']; ?>">
<button type="button" class="btn btn-default btn-circle"><i class="fa fa-pencil-square-o"></i></button>
</a>
<button type="button" class="btn btn-danger btn-default btn-circle" id="<?php echo $r['attr_val_id']; ?>" name="deleteRecord"><i class="fa fa-times"></i></button></td>
</tr>
<?php $c++;}?>
</tbody>
</table>
</div>
<!-- /.table-responsive -->
</div>
</div>
JQuery
$('#attr_val_form').submit(function(event) {
//$('.form-group').removeClass('has-error'); // remove the error class
//$('.help-block').remove(); // remove the error text
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
var formData = {
'attr_val' : $('input[name=attr_val]').val(),
'attr_id' : $('input[name=attr_id]').val(),
'sortorder' : $('input[name=sortorder]').val(),
};
// process the form
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : 'admin_operation.php?mode=add_attr_value', // the url where we want to POST
data : formData, // our data object
cache: false,
success: function(data)
{
if($.trim(data)== 'yes')
{
$("#value_table").html($("#value_table").html());
$("#notice")
.show()
.html('<div class="alert alert-success"<strong>Successfully !</strong> record added.</div>')
.fadeOut(3000);
}
else
{
$("#notice")
.show()
.html('<div class="alert alert-danger"<strong>Error !</strong>Record already exist.</div>')
.fadeOut(10000);
}
}
})
// using the done promise callback
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
});
});
I guess what you think this line should do is get the data from the response and substitute the same tag in your DOM:
$("#value_table").html($("#value_table").html());
You should use something like that instead:
$("#value_table").html($.parseHTML(data).find("#value_table").html());
This code has not been tested, but the main idea is to parse the data parameter and the find the #value_table element.
More info here: http://api.jquery.com/jquery.parsehtml/
As you say it seems like 'admin_operation.php?mode=add_attr_value' not success, try to call to always function instead success (for debugging it).
if the always function called successfully you have to return true from admin_operation.php
if not you have a problem on admin_operation.php after the insertion.
i have the following table:
<table id="list_table" class="global" border="0" cellpadding="4" cellspacing="0">
<thead>
<tr>
<th>Grund</th><th>Von</th><th>Bis</th><th>Beschreibung</th><th></th></tr>
</thead>
<tbody>
<tr>
<td><select name="grund[1][1]">
<option value="krank">Krankheit</option>
<option value="urlaub" selected="selected">Urlaub</option>
<option value="sonstiges">Sonstiges</option>
</select></td><td><input name="von[1][1]" value="11.08.2011" onclick="displayDatePicker('von[1][1]')" type="text"></td><td><input name="bis[1][1]" value="16.09.2011" onclick="displayDatePicker('bis[1][1]')" type="text"></td><td><input name="beschreibung[1][1]" value="Blau machen" type="text"></td><td><img src="images/save.png"> <img src="images/delete.png"></td></tr>
</tbody>
</table>
And my JQuery is:
$('a[class*=saveChangedEntry]').click(function(event) {
event.preventDefault();
alert('That's it!');
});
So if I click on the link nothing happens ;(
And if i call the class in the more direct way ... even this does not work.
Any hints?
UPDATE:
Ok, something I didn't think about it and you could not know. The table is generated as a result of a couple of events, so I think I need to add the live() function to these links.
alert('That's it!');
is not properly escaped:
alert('That\'s it!');
Example
Make sure you wrap your code in a document.ready. Also the text you've placed inside the alert contains an unescaped quote:
$(function() {
$('a[class*="saveChangedEntry"]').click(function(evt) {
evt.preventDefault();
alert('That\'s it!');
});
});
Ok, perhaps I'm not getting the problem here too well, but I think that the issue is with the selector...
$(document).ready(function(){
$("a.saveChangedEntry").click(function(evt){
evt.preventDefault();
alert("foo!");
});
});
Hope I can help