I've spent several hours looking at examples and docs trying to figure out how to POST additional parameters to editurl, and have yet to figure this out. I'm using Perl Catalyst.
Though I don't have it all coded in the controller, I am getting what I need POSTed to add and edit, but not to delete records. I need inv_id to be POSTed to the server for my controller to delete a record.
Controller/Root.pm:
package MyFirstGrid::Controller::Root;
use Moose;
use namespace::autoclean;
BEGIN {extends 'Catalyst::Controller'}
with 'Catalyst::TraitFor::Controller::jQuery::jqGrid';
__PACKAGE__->config(namespace => '');
sub index :Path :Args(0) {
my ($self, $c) = #_;
$c->detach($c->view("TT"));
}
sub getdata :Local {
my ($self, $c) = #_;
my $inv_rs = $c->model('DB::Inventory')->search({});
$inv_rs = $self->jqgrid_page($c, $inv_rs);
my #row_data;
while (my $inv = $inv_rs->next) {
my $single_row = {
cell => [
$inv->inv_id,
$inv->client_id,
$inv->amount,
$inv->tax,
$inv->total,
$inv->note,
],
};
push #row_data, $single_row;
}
$c->stash->{json_data}{rows} = \#row_data;
$c->detach($c->view("JSON"));
}
sub postrow :Local {
my ($self, $c) = #_;
my $data = $c->req->params;
my $inv_rs = $c->model('DB::Inventory')->search({inv_id => $data->{inv_id}});
$inv_rs->update({
client_id => $data->{client_id},
amount => $data->{amount},
tax => $data->{tax},
total => $data->{total},
note => $data->{note},
});
$c->res->status(204);
}
sub default :Path {
my ($self, $c) = #_;
$c->response->body('Page not found');
$c->response->status(404);
}
sub end : ActionClass('RenderView') {}
__PACKAGE__->meta->make_immutable;
1;
index.tt:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My First Grid</title>
<link rel="stylesheet" type="text/css" media="screen" href="[% c.uri_for('/static/css/cupertino/jquery-ui-1.8.22.custom.css') %]" />
<link rel="stylesheet" type="text/css" media="screen" href="[% c.uri_for('/static/css/ui.jqgrid.css') %]" />
<style type="text/css">
html, body {
margin: 0;
padding: 0;
font-size: 75%;
}
</style>
<script src="[% c.uri_for('/static/js/jquery-1.7.2.min.js') %]" type="text/javascript"></script>
<script src="[% c.uri_for('/static/js/i18n/grid.locale-en.js') %]" type="text/javascript"></script>
<script src="[% c.uri_for('/static/js/jquery.jqGrid.min.js') %]" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
$("#list").jqGrid({
url: "[% c.uri_for("getdata") %]",
datatype: 'json',
mtype: 'GET',
colNames:['Inv No', 'Client ID', 'Amount','Tax','Total','Notes'],
colModel :[
//{name:'inv_id', index:'inv_id', editable:true, hidden:true, editrules:{edithidden:false}, hidedlg:true},
{name:'inv_id', index:'inv_id', editable:true, hidden:true},
{name:'client_id', index:'client_id', width:55, editable:true, editoptions:{size:10}},
{name:'amount', index:'amount', width:80, align:'right', editable:true, editoptions:{size:10}},
{name:'tax', index:'tax', width:80, align:'right', editable:true, editoptions:{size:10}},
{name:'total', index:'total', width:80, align:'right', editable:true, editoptions:{size:10}},
{name:'note', index:'note', width:150, sortable:false, editable: true, edittype:"textarea", editoptions:{rows:"2",cols:"20"}}
],
pager: '#pager',
rowNum:10,
rowList:[10,20,30],
sortname: 'inv_id',
sortorder: 'desc',
viewrecords: true,
caption: 'My First Grid: Navigator',
editurl: "[% c.uri_for("postrow") %]",
height: 240
});
jQuery("#list").jqGrid('navGrid','#pager',
{}, //options
{height:280,reloadAfterSubmit:false}, // edit options
{height:280,reloadAfterSubmit:false}, // add options
{reloadAfterSubmit:false}, // del options
{} // search options
);
});
</script>
</head>
<body>
<table id="list"><tr><td/></tr></table>
<div id="pager"></div>
</body>
</html>
I suppose that the origin of the problem which you have is in filling of the grid. During filling of the grid all grid's rows (<tr> elements) get the id attribute. During editing and deleting of the rows the value of id attribute of the corresponding row will be send always to the server. It's important to know that the values of id attributes have to be unique on the page. If the values of inv_id are unique, that you can use this values directly as the id. To inform jqGrid about the choice you can either add jsonReader: {id: "inv_id"} as additional grid parameter or just to add key: true property to the definition of the inv_id column.
I don't use Perl Catalyst myself, but the part where you fill the grid data (see my $single_row = { cell => [...]}) seems to me should contain id property additionally to cell property (something like $single_row = {cell => [...], id => $inv->inv_id}). If the inv_id is unique it would be better enough to add key: true to the definition of the inv_id column and your problem will be already solved.
If you already use another value of id and you really need to have both values: the id and inv_id then you can use for example onclickSubmit callback of delete options. The
onclickSubmit: function (options, rowid) {
return {inv_id: $(this).jqGrid("getCell", rowid, "inv_id")};
}
I mean to use the following
$("#list").jqGrid('navGrid', '#pager', {}, //options
{height: 280, reloadAfterSubmit: false}, // edit options
{height: 280, reloadAfterSubmit: false}, // add options
{ // del options
reloadAfterSubmit: false,
onclickSubmit: function (options, rowid) {
return {inv_id: $(this).jqGrid("getCell", rowid, "inv_id")};
}
}
);
As the result the data posted to the server during Delete operation will be extended with additional parameter inv_id.
Related
I have the invisible reCAPTCHA set up, but it doesn't seem to want to call my callback function. My form looks like:
<form id='ContactAgentForm' name='ContactAgentForm' class='custom-form-widget-form standard_form' action='contact_agent' listing_id=1233445>
...
<div class='field captcha-field recaptcha_field' >
<div id='g-recaptcha-div' class="g-recaptcha" ></div>
</div>
...
<div class="field button-field">
<button class="button button-primary"><span>Send</span></button>
<a class="button button-cancel btn-close" href="#cancel"><span>Cancel</span></a>
</div>
</form>
In the javascript, I want to handle the fact that there might be multiple forms on the page, so I create a list of all the forms. For each form, I attach/render the reCAPTCHA logic, attaching my callback with the form passed as a parameter:
<script>
var $form_list = jQuery("form.custom-form-widget-form");
var onFormPageSubmit = function(token, $form ) {
console.log("Got here! ", token );
var field = $form.find('.g-recaptcha-response')[0];
field.value = token;
$form[0].submit();
};
var onloadCallback = function() {
$form_list.each( function() {
var $form = jQuery(this);
var $recaptcha = $form.find( ".g-recaptcha" );
if ( $recaptcha.length )
{
var recaptchaId = grecaptcha.render($recaptcha[0], {
'callback': function (token) { onFormPageSubmit(token, $form); },
'sitekey': "{$captcha_config.invisible_captcha_site_key}",
'size': 'invisible',
'badge': 'inline'
});
$form.data("recaptchaid", recaptchaId);
}
});
};
</script>
And just below that, I load the recaptcha/api.js file:
<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=onloadCallback"></script>
With some judicial 'console.log' statements, we get through all of the code EXCEPT for the callback (onFormPageSubmit). The "protected by reCAPTCHA" logo is there, but it seems that the form is just submitted, ignoring the reCAPTCHA call altogether.
All help appreciated.
Somewhere along the line, the validation function for the form was lost (it's in another file). The validation function was attached to the button, and it executed something like this:
$submit_button.on( 'click', function( event ) {
event.preventDefault();
// get the recaptchaid from form data
var $recaptcha_id = $form.data( "recaptchaid" );
if ( $recaptcha_id != undefined )
{
grecaptcha.execute($recaptcha_id);
}
} );
The "grecaptcha.execute" is the important thing - this is what triggers the actual reCAPTCHA call.
currently I am trying to show 3 Google Charts on a page, but the page is blank, it does not display any of the charts. Originally the 1st chart was displayed, then it worked but ever since I attached the 2nd one (even if I deleted that so only the 1st one would be shown again), the page I have is totally blank and I don't know why.
Could you please help me?
Here is my code (I set the $conn and $_SESSION variables at the top of my page):
EDIT: Here is a picture about the source code in my browser:
[![sourcecode][1]][1] What I don't understand is that it looks like it would expect other values to data1 and data2 and that is why the charts are not displayed...
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dashboard</title>
<link rel="stylesheet" href="styles.css">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Load Charts and the corechart package.
google.load('current', callback: drawCharts, {packages:['column', 'pie']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawCharts);
// Callback that creates and populates a data table, instantiates the pie chart, passes in the data and draws it.
function drawCharts() {
var data1 = google.visualization.arrayToDataTable([
['Classification', 'Number of assets'],
<?php
if ($_SESSION['user_type'] == 'admin') {
$sql = "SELECT Classification, count('Classification') as count FROM `assets` GROUP BY Classification ORDER BY FIELD(Classification, 'high', 'medium', 'low')";
}else{
$sql = "SELECT Classification, count('Classification') as count FROM `assets` WHERE Responsible =".$_SESSION['name']." GROUP BY Classification ORDER BY FIELD(Classification, 'high', 'medium', 'low')";
}
$result = mysqli_query($conn,$sql);
while ($result2=mysqli_fetch_array($result)) {
echo "['".$result2['Classification']."',".$result2['count']."],";
}
?>
]);
var data2 = google.visualization.arrayToDataTable([
['Risks', 'Percentage'],
<?php
if ($_SESSION['user_type'] == 'admin') {
$sql = "SELECT Compliant = (SELECT count('id') FROM `risks` WHERE targetrisk >= residualrisk), Non-compliant = (SELECT count('id') FROM `risks` WHERE targetrisk < residualrisk) FROM risks ";
}else{
$sql = "SELECT Compliant = (SELECT count('id') FROM `risks` WHERE responsible =".$_SESSION['name']." AND targetrisk >= residualrisk), Non-compliant = (SELECT count('id') FROM `risks` WHERE ".$_SESSION['name']." AND targetrisk < residualrisk) FROM risks ";
}
$results = mysqli_query($conn,$sql);
while ($result2=mysqli_fetch_array($results)) {
echo "['".$result2['Compliant']."',".$result2['Non-compliant']."],";
}
?>
]);
var data3 = google.visualization.arrayToDataTable([
['Assets', 'Percentage'],
<?php
if ($_SESSION['user_type'] == 'admin') {
$sql = "SELECT count('Asset_name') as Assets, count(`risks`.`assettag`) as Compliant assets FROM `assets`, `risks` JOIN `assettag` ON `assets`.`Tag` = `risks`.`assettag` ";
}else{
$sql = "SELECT count('Asset_name') as Assets, count(`risks`.`assettag`) as Compliant assets FROM `assets`, `risks` JOIN `assettag` ON `assets`.`Tag` = `risks`.`assettag` AND responsible =".$_SESSION['name']."";
}
$results = mysqli_query($conn,$sql);
while ($result2=mysqli_fetch_array($results)) {
echo "['".$result2['Assets']."',".$result2['Compliant assets']."],";
}
?>
]);
var options1 = {
title: 'Asset classification',
legend: { position: 'none' },
width: 900,
height: 500
};
var options2 = {
title: 'Risk compliance',
legend: { position: 'none' },
width: 900,
height: 500
};
var options3 = {
title: 'Asset compliance',
legend: { position: 'none' },
width: 900,
height: 500
};
var chart1 = new google.visualization.ColumnChart(document.getElementById("columnchart"));
chart1.draw(data1, options1);
var chart2 = new google.visualization.PieChart(document.getElementById("piechart"));
chart2.draw(data2, options2);
var chart3 = new google.visualization.PieChart(document.getElementById("piechart2"));
chart3.draw(data3, options3);
}
</script>
</head>
<body>
<div id="columnchart"></div>
<br>
<div id="piechart" ></div>
<br>
<div id="piechart2" ></div>
</body>
</html>
[1]: https://i.stack.imgur.com/f2u3D.png
Im a noob with Laravel 4 and the contact form things is giving me some trouble to make it work.
Found few things, all using controllers but I just need it in the route.
How to do the route for a simple contact form (name,email and message) to send the datas to an admin email box?
Cheers
Here's a quick and dirty way to send e-mails using just your routes:
Create your routes
Route::get('contact', function() {
return View::make('contact');
});
Route::post('contact', function() {
$fromEmail = Input::get('email');
$fromName = Input::get('name');
$subject = Input::get('subject');
$data = Input::get('message');
$toEmail = 'manager#company.com';
$toName = 'Company Manager';
Mail::send('emails.contact', $data, function($message) use ($toEmail, $toName, $fromEmail, $fromName, $subject)
{
$message->to($toEmail, $toName)
$message->from($fromEmail, $fromName);
$message->subject($subject);
});
});
Create a app/views/contact.php
<html>
<body>
<form action="/contact" method="POST">
Your form
</form>
</body>
</html>
Create app/views/emails/contact.php
<html>
<body>
Message: {{$data}}
</body>
</html>
And you need to configure
app/config/mail.php
My Telerik MVC grid is Ajax bound and I need to ability to apply custom filtering via two checkboxes (in the DIV at the top). When a checkbox is checked, the parameters would be set and the grid is reloaded. This is working fine. During the initial load the data is sorted based on the sorting settings in Telerik, but after I click a checkbox, the data is ordered by record Id and no longer by Priority. If I then hit F5 the page is reloaded and the data is sorted correct. The sorting might be a parameter for grid.rebind() or provided in OnDataBinding, but so far I have not found what I am looking for.
QUESTION: How do I specify the sorting order in the OnDataBinding or perhaps in another client event.
Here is my code:
<div style="float:right;width:600px;text-align:right">
<span>My Items <%=Html.CheckBox("newItems") %></span>
<span>Closed Items <%=Html.CheckBox("Inactive") %></span>
</div>
<% Html.Telerik().Grid<IssueModel>()
.Name("Grid")
.PrefixUrlParameters(false)
.Columns(col =>
{
col.Bound(o => o.Title);
col.Bound(o => o.Priority).Width(50).Title("Priority ID");
col.Bound(o => o.PriorityName).Width(100).Title("Priority");
col.Bound(o => o.IssueStateName).Width(100).Title("Status");
col.Bound(o => o.AssignedToName).Width(140).Title("Assigned To");
})
.DataBinding(d => d.Ajax().Select("AjaxSelect", "Ticket", new { isNew = false, isInactive = false }))
.ClientEvents(e => e.OnDataBinding("onDataBinding"))
.Sortable(s => s
.SortMode(GridSortMode.MultipleColumn)
.OrderBy(order =>
{
order.Add(o => o.Priority);
order.Add(o => o.Sequence);
})
)
.Pageable(p => p.PageSize(15))
.Filterable()
.Render();
%>
<script type="text/javascript">
function onDataBinding(e) {
e.data = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
e.orderBy = "Severity~desc~Ranking~asc";
}
$("input[type='checkbox']").click(function () {
var grid = $('#Grid').data('tGrid');
var param = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
grid.rebind(param);
});
</script>
I found the solution in case others need the answer. I used grid.sort() in place of grid.rebind(); The sort method takes a string in the format: column-name dash direction. Example First
<script type="text/javascript">
function onDataBinding(e) {
e.data = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
}
$("input[type='checkbox']").click(function () {
var grid = $('#Grid').data('tGrid');
var param = {
isNew: $("#newItems").is(':checked'),
isInactive: $("#Inactive").is(':checked')
};
grid.sort("Severity-desc~Ranking-asc";);
//grid.rebind(param);
});
</script>
The snippet below is supposed to get a friends list from a user's Facebook profile into my application:
<script
type="text/javascript"
src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php">
</script>
<script type="text/javascript">
FB_RequireFeatures(
["XFBML"],
function() {
FB.Facebook.init("xxxxxxxx","xd_receiver.htm");
FB.Facebook.get_sessionState().waitUntilReady(
function() {
FB.Facebook.apiClient.friends_get(
null,
function(result,ex){window.alert("friends list :" + result);}
);
}
);
}
);
</script>
Instead of the name of my friends I get some integer. I couldn't guess why. It would be nice to know why my approach doesn't work.
Your approach does work, but as Documented on the Facebook Developer Wiki, the function FB.ApiClient.Friends_get which you call doesn't return the names of friends, it returns an array of their user IDs which are large (often bigger than integer) number values. You will need to use an additional function, FB.ApiClient.users_getInfo, in order to return the name(s) of users. You also don't need to call FB.Facebook.ApiClient, you can bypass the Facebook object using FB.ApiClient directly.
Here is an example (untested, but should give you the idea):
<script type="text/javascript" src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"></script>
<script type="text/javascript">
FB_RequireFeatures(
["XFBML"],
function() {
FB.Facebook.init("xxxxxxxx","xd_receiver.htm");
FB.Facebook.get_sessionState().waitUntilReady(
function() {
FB.ApiClient.friends_get(
null,
function(result,ex) {
FB.ApiClient.users_getInfo(result, 'name',
function(friendNames, exec) {
window.alert("first name in friends list: " + friendsNames[0]);
}
)
}
);
}
);
}
);
</script>
I believe you have to do:
FB.ApiClient.friends_get(
new Array(),
Which I saw on the developer site.