I'm using .NET Charts to create some dynamic charts from a table in a database, and each chart is a separate view, with a corresponding action in the controller.
Then they are displayed in a main view as images:
<img src="~/Controller/Chart1" class="centered" />
Now I want to be able to filter the charts by date, and I've added the parameters to the actions and a couple datepickers for a start date and an end date.
I'm trying to refresh the charts using Ajax, but I'm having trouble. Without Ajax, the filter works, but redirects to a page containing just the updated chart.
With Ajax, nothing happens, or rather, if I set the UpdateTargetId to a div it gets filled with text, like byte code or something.
This is what I'm using:
<div>
using (Ajax.BeginForm("Chart1", "controller",
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "Chart1"
}))
{
<p>
<input type="text" name="begindate" class="datefield" placeholder="Begin Date" />
<input type="text" name="enddate" class="datefield" placeholder="End Date" />
<input type="submit" value="Filter" />
</p>
<img src="~/controller/Chart1" class="centered" />
</div>
How can I fix this problem?
You need to pass the dates to your action method and let the action method uses these dates to generate a filtered data set which will be used to generate the chart.
You can simply use jQuery Ajax to do this.
<div>
<input type="text" name="begindate" class="datefield" placehold="Begin Date" />
<input type="text" name="enddate" class="datefield" placeholder="End Date" />
<input type="submit" id="btnFilter" value="Filter" />
<img src="~/controller/Chart1" id="chartImg" class="centered" />
</div>
Now when user clicks the form, pass the dates
$(function(){
$("#btnFilter").click(function(e){
e.preventDefault();
var d1 = $("input[name='begindate']").val();
var d2 = $("input[name='enddate']").val();
var url = "#Url.Action("Chart1", "YourControllerName")";
url += "?beginDate=" + d1 + "&endDate=" + d2;
$("#chartImg").attr("src", url);
});
});
Now of course your action method should accept the dates and return the data as needed:
public ActionResult Chart1(DateTime beginDate,DateTime endDate)
{
// Return the chart image
}
I am using the Url.Action action method to generate the correct path to the Chart1 action method. This code will work if your JavaScript code is inside a Razor view. If your code is inside an external js file, Use the approach mentioned in this post
Related
I have this view and everything fine with Ajax.BeginForm:
<h2>Index</h2>
#using (Ajax.BeginForm("Search", new AjaxOptions {
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "users"
})) {
<input name="q" type="text" />
<input type="submit" value="Search" />
}
<div class="table-responsive" id="users">
</div>
But, i have a little question.
Right now, when i open this page, there are no table with data - it loads only when form is submitted.
So, my question: is it possible to have preload data (without adding other code)?
When page is loaded, i would like to have already all data without filtering (input uses for filtering when value is typed and form submitted).
Just call your Search action from users div when the page loads. You may not specify any parameter or use the default one. I assume you have something like this:
public ActionResult Search(string q)
{
var users = _usersRepository.GetAll();
if(!string.IsNullOrEmpty(q))
users = users.Where(user => string.Equals(user.Name, q));
return PartialView("_Search", users);
}
And in the view:
<div class="table-responsive" id="users">
#Html.Action("Search")
</div>
i'm trying to add an entry into my database and update a table i have created using AJAX. I think i'm halfway there, i can send my form contents to the "partial" page, but thats where it gets stuck?
Here's my content page:
#{
Layout = "~/_SiteLayout.cshtml";
WebSecurity.RequireAuthenticatedUser();
var db = Database.Open("StayInFlorida");
var rPropertyId = Request.QueryString["PropertyID"];
var Roominfo = "SELECT * FROM RoomInfo WHERE PropertyID=#0";
var qRoominfo = db.Query(Roominfo, rPropertyId);
}
<h2>Current Rooms</h2>
<table id="room-table" class="table table-bordered">
<tr>
<th>Room Name</th>
<th>Room Type</th>
<th>Room Description</th>
</tr>
#foreach(var row in qRoominfo){
<tr>
<td>#row.RoomName</td>
<td>#row.RoomType</td>
<td>#row.RoomDescription</td>
</tr>
}
</table>
<form id="add-room-form" action="#Href("~/Partials/AddRoom")">
<div class="row">
<span class="label"><label for="title">Room Name:</label></span>
<input type="text" name="roomname" id="roomname" size="50" />
</div>
<div class="row">
<span class="label"><label for="title">Room Type:</label></span>
<input type="text" name="roomtype" id="roomtype" size="50" />
</div>
<div class="row">
<span class="label"><label for="title">Room Description:</label></span>
<input type="text" name="roomdescription" id="roomdescription" size="50" />
</div>
<input type="hidden" name="propertyid" value="#rPropertyId" />
<button class="btn btn-success" id="submitbutton">Submit</button>
</form>
<script type="text/javascript">
$(function(){
$('#submitbutton').click(function(){
$.ajax({
type: "POST",
url: "/Partials/AddRoom",
data: $("#add-room-form").serialize(),
dataType: "text/plain",
success: function (data) {
$('#room-table').html(data);
}
return false;
});
});
});
</script>
and here is the partial page which "should" insert the data into the database:
#{
var db = Database.Open("StayInFlorida");
var sql = "INSERT INTO RoomInfo (PropertyID, RoomName, RoomType, RoomDescription, LastModified) " +
"VALUES (#0, #1, #2, #3, GetDate())";
var propertyid = Request["propertyid"];
var roomname = Request["roomname"];
var roomtype = Request["roomtype"];
var roomdescription = Request["roomdescription"];
db.Execute(sql, propertyid, roomname, roomtype, roomdescription);
}
In theory, it should write the info to the database, and then refresh my table, so im guessing something isn't quite right with the javascript?
You cannot sent the data through an ajax call is because you cannot even start the request. You are using the function to trigger when a click is made. But there will be no click event.
Reason: There is no button with the ID for click event. See Click trigger issue section below.
Tip: To check whether there is any Request to the server or not, you should make use of this. In every browser when you press F12 you get Developer Tools opened. Make sure you are on network tab. You will be able to check any network request made to server through there. Ajax requests are also saved there as a log, there status and everything is present there. That will be a basic but a powerfull tool to help you out in understanding how Ajax requests are made.
There are certain issues in your code too.
Issue in the HTML: There is an error in your code, look at the submit button. Its having code as:
<button class="btn btn-success" type="submit" value="Submit"/>Submit</button>
Which should be:
<button class="btn btn-success" type="submit" value="Submit">Submit</button>
And then, I should change that too the following because the type="submit" will submit the form instead of creating an ajax request. I used your page in my website and just replaced the DataBase objects and replaced them with simple Response like Response.Write() and wrote the variables that I caught:
<button class="btn btn-success" id="submitbutton">Submit</button>
So the code that I changed the above one to is like this:
#{
if(IsPost){
var propertyid = "1";
var roomname = Request["roomname"];
var roomtype = Request["roomtype"];
var roomdescription = Request["roomdescription"];
var lastmodified = DateTime.Now;
// here you will write the data to database using Database.Execute
// Remember you should write the ajax response
// here as a result of Response.Write()
// However if you still want to load that page, its OK!
}
}
As mentioned earlier, you were write the propertyid as "'1'" I changed that to "1". But in case you want to execute as "'1'" its ok too.
Click trigger issue:
There were some other issues too. You were using:
$('#submitbutton').click(function(){
But there was no button with the ID submitbutton. So I changed the id of the button you were using there.
What I changed in your code:
What change I made in your code was I changed the POST request to GET. To have a look at what variables are being sent to server and what results I get. I had it easier to make use of this code as GET request was easily able to check then POST request.
If you still want to use POST request you should try to serialize() the form as JSON and send it to server. But GET will be easy.
Then I gave another field to the $.ajax section as:
data: 'roomname=' + $('#roomname').val() +
'roomtype=' + $('#roomtype').val() +
'roomdescription=' + $('#roomdescription').val(),
This will create a string of the data to be sent. And then it will be caught on that page. And I removed if(IsPost) too. I was able to get the result of the Response. So what you can do is to change the Response of the request and write is as:
$("#room-table").html(response);
And the table will be changed! This will remove the previous data in the table Or even whole of the table and update it with the data recieved from the Response. And then I was able to send the request to server, process the QueryString and then write a response and then using $('#idofelement').html(response) I wrote it in the specific area. You can try it as I did.
The full code that I used was:
One the main page I had this code:
#{
Layout = "~/_SiteLayout.cshtml";
}
<h2>Current Rooms</h2>
<div class="row">
<span class="label"><label for="title">Room Name:</label></span>
<input type="text" name="roomname" id="roomname" size="50" />
</div>
<div class="row">
<span class="label"><label for="title">Room Type:</label></span>
<input type="text" name="roomtype" id="roomtype" size="50" />
</div>
<div class="row">
<span class="label"><label for="title">Room Description:</label></span>
<input type="text" name="roomdescription" id="roomdescription" size="50" />
</div>
<button class="btn btn-success" id="submitbutton" value="Submit" >Submit</button>
<script type="text/javascript">
$(function(){
$('#submitbutton').click(function(){
$.ajax({
url: '/Partials',
data: 'roomname=' + $('#roomname').val() + 'roomtype=' +
$('#roomtype').val() + "roomdescription=" +
$('#roomdescription').val(),
dataType: 'text',
contentType: 'text/html',
success: function(response) {
$("#body").html(response);
},
error: function(data){
alert('Something went wrong');
}
});
});
});
</script>
I changed the page to partials only and used it. Here is the content for that page.
#{
var propertyid = "1";
var roomname = Request["roomname"];
var roomtype = Request["roomtype"];
var roomdescription = Request["roomdescription"];
var lastmodified = DateTime.Now;
Response.Write("Room name: " + roomname + "<br>Room Type: "
+ roomtype + "<br>Room Description: " + roomdescription +
"<br>Property: " + propertyid);
}
Now its upto you to use the Database variables here. Where I used Response.Write and other codes You can use the Database methods. And also you can add WebSecurity method.
The Database.Execute method requires the SQL to be executed to be passed in first. You don't appear to be passing it in at all. Also, I assume that PropertyId is an integer? If so, you should not surround it in quotes. In fact, you should try delimiting values that will be passed in via parameter at all. That's one of the benefits of using parameters. Try this:
#{
if(IsPost){
var db = Database.Open("StayInFlorida");
var sql = "INSERT INTO RoomInfo (PropertyID, RoomName, RoomType, RoomDescription, LastModified) " +
"VALUES (#0, #1, #2, #3, GetDate())";
var propertyid = 1;
var roomname = Request["roomname"];
var roomtype = Request["roomtype"];
var roomdescription = Request["roomdescription"];
db.Execute(sql, propertyid, roomname, roomtype, roomdescription);
}
}
You are hardcoding the Properytid at the moment. If you want that to be dynamic, add a hidden field to your AJAX form and set the value to rPropertyId:
<input type="hidden" name="propertyId" value="#rPropertyId" />
Then you can alter the 4th line in the snippet above:
var propertyId = Request["propertyId"];
I want to improve my website and figured out a good way to do it was by submitting forms via AJAX. But, I have so many forms that it would be inpractical to do $('#formx').submit(). I was wondering if there was a way to do this automatically by making an universal markup like;
<form class="ajax_form" meta-submit="ajax/pagename.php">
<input type="text" name="inputx" value="x_value">
<input type="text" name="inputy" value="y_value">
</form>
And have this submit to ajax/pagename.php, where it automatically includes inputx and inputy?
This would not only save me a lot of time but also a lot of lines of code to be written.
First question so I hope it's not a stupid one :)
Something like this should work for all forms. It uses jQuery - is this available in your project? This specific code chunk hasn't been tested per say, but I use this method all the time. It is a wonderful time saver. Notice I changed meta-submit to data-submit so that its value can be fetched using $('.elemenet_class').data('submit');
HTML
<!-- NOTE: All Form items must have a unique 'name' attribute -->
<form action="javascript:void(0);" class="ajax_form" data-submit="ajax/pagename.php">
<input type="text" name="inputx" value="x_value">
<input type="text" name="inputy" value="y_value">
<input type="submit" value="go" />
</form>
JavaScript
$('.ajax_form').submit(function(e){
var path = $(this).attr('data-submit'); //Path to Action
var data = $(this).serialize(); //Form Data
$.post(path, {data:data}, function(obj){
});
return false;
})
PHP
//DEBUGGING CODE
//var_dump($_POST);
//die(null);
$data = $_POST['data'];
$inputx = $data['inputx'];
$inputy = $data['inputy'];
you can create ajax fot text boxes so that it can update to database whenever change the focus from it.
<form id="ajax_form1">
<fieldset>
<input type="text" id="inputx" value="x_value" />
<input type="text" id="inputy" value="y_value" />
</fieldset>
</form>
<script>
$(document).ready(function()
{
$("form#ajax_form1").find(":input").change(function()
{
var field_name=$(this).attr("id");
var field_val=$(this).val();
var params ={ param1:field_name, param2:field_val };
$.ajax({ url: "ajax/pagename.php",
dataType: "json",
data: params,
success: setResult
});
});
});
</script>
Basically the template wont render to a ScrollView using kendo.render(template, response) but WILL work with content = template(response) - BUT this has no styling in view -- see comment below
How to make the template render with kendo stylign in view?
BTW response from api call is JSON:
{"event_id":"5","stamp":"2013-01-24 06:00:00","type":"Event Type","loc":"Location","status":"1"}
<!-- eventDetail view -------------------------------------------------------------------------------------------------->
<div data-role="view" id="view-eventDetail" data-show="getEventDetailData" data-title="eventDetail">
<header data-role="header">
<div data-role="navbar">
<span data-role="view-title"></span>
<a data-align="right" data-role="button" class="nav-button" href="#view-myEvents">Back</a>
</div>
</header>
<div id="eventDetail" data-role="page"></div>
</div>
<script id="eventDetail-template" type="text/x-kendo-template">
--><form id="addEventForm"><p>
<input name="event_type" id="event_type" data-min="true" type="text" value="#= type #" />
</p>
<p>
<input name="event_loc" id="event_loc" data-min="true" type="text" value="#= loc #" />
</p>
<p>
<input name="event_date_time" id="event_date_time" data-min="true" type="datetime" value="#= stamp#" />
</p>
<p>
Share this
<input data-role="switch" id="event_share" data-min="true" checked="checked" value="1"/></p>
<p>
<input type="button" id="eventCancelButton" style="width:30%" data-role="button" data-min="true" value="Cancel" />
<input type="submit" id="eventDoneButton" style="width:30%" data-role="button" data-min="true" value="Done" />
</p></form><!--
</script>
<script>
//eventDetail engine
function getEventDetailData(e) {
$.ajax({
url: 'http://localhost/mpt/website/api/event_details.php?',
type: "GET",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: { userID: 2, eventID: e.view.params.id },
success: function(response) {
console.log(response);
var template = kendo.template($("#eventDetail-template").html()),
content = template(response);//works but no kendo css
//content = kendo.render(template, response);not working
$("#eventDetail")
.kendoMobileScrollView()
.data("kendoMobileScrollView")
.content("<!--" + content + "-->");
}
});
}</script>
The widget classes (like km-button) are not added until the widget is initialized.
The template() and render() functions just return the template as a string with the data replaced (replaces #=foo# with the value of the foo property) but does not init all the widgets. In fact, it coldn't initialize the widgets if it wanted to singe it just returns a text string, not DOM elements. The initialization of the widgets is usually done by the parent widget that is using the template.
render() is not working in your case because its 2nd argument is supposed to be an array. All it does is call the given template function once per item in the array and concatenate the results. If you instead did:
var content = kendo.render(template, [response]); // wrap response in an array
it would return the same text string as template(response). It just provides a way to apply the same template to many items at once.
Normally when you create a widget, in your case calling .kendoMobileScrollView() you would expect it to turn any HTML contents of that element into widgets too, but it looks like the ScrollView widget doesn't do this. I think its intent may have been to just display pages of static content, not other widgets.
There is a Kendo method that isn't listed in the docs, kendo.mobile.init(contents); that you might be able to use to turn your template string into widgets. When I tried it in a jsFiddle it threw some error for me, but you could try something like:
var content = template(response); // apply response to template
var contentElements = $(content); // turn the string into DOM elements
kendo.mobile.init(contentElements); // turn elements into widgets (this throws error for me)
$("#eventDetail").html(contentElements); // add contents to the desired element
$("#eventDetail").kendoMobileScrollView(); // create the scroll view
Also, what is with the end and begin comment bits hanging off the ends of the template? I don't see why those are needed. Might be better to remove them.
The ScrollView widget is supposed to take a series of <div> elements as its children. It then pages between them as you swipe left/right across the control. I don't see you adding a series of <div>s anywhere.
need a little help. My jQuery was going smooth today until I hit a wall. I am trying to have multiple forms (individual line items) editable on the fly via AJAX, with a text submission link or some kind of submit button. Problem is, I can get it to submit the form via the AJAX, but without any of the data from the form... i.e. hit submit, it sends the request, but no querystring. Can someone please help me identify what's missing?
Here is my jquery:
$('.submitLineChanges').click(function() {
var formID = $(this).closest('form').attr('ID')
datastring = $(formID).serialize();
$.ajax({
type:'POST',
url: 'update_ajax.asp',
data: datastring,
success: function(response) {
alert("Success " + id)
//$('#ContactForm').find('.form_result').html(response);
}//end ajax options
});//end ajax
return false;
});//end of click function
And my form:
<form id="line-item-<%= intRecID %>-form" class="submitLineForm">
<input type="hidden" name="UpdateLineItem" value="true" />
<span class="edit" id="edit-line-<%= intRecID %>" style="display: none;">
<span class="quantity"><input name="part_qty" id="part_qty_<%= intRecID %>" type="text" value="<%=FormatNumber(rs("quote_part_qty"),0)%>"></span>
<span class="partno"><input name="part_no" id="part_no_<%= intRecID %>" type="text" value="<%=rs("quote_part_id")%>"></span>
<span class="descrip"><Textarea name="part_descrip" type="text" id="descrip<%= intRecID %>" rows="3"><%=rs("quote_part_descrip")%></Textarea></span>
<span class="sellprice">$<input name="part_sale" id="part_sale_<%= intRecID %>" type="text" value="<%=FormatNumber(rs("quote_part_sale"),2)%>"></span>
<span class="margin" id="emargin_<%= intRecID %>"><%=margin%></span>
<span class="cost"><strong>Cost: </strong>$<input name="part_cost" id="part_cost_<%= intRecID %>" type="text" value="<%=FormatNumber(cost,2)%>"></span>
<span class="wt"><strong>Weight: </strong><input name="part_wt" id="part_wt_<%= intRecID %>" type="text" value="<%=FormatNumber(rs("quote_part_wt"),2)%>"></span>
<span class="update"><input type="button" value="Save Changes" class="submitLineChanges" /></span>
</span>
</form>
As you should be able to tell, I'm running this in ASP. The form is for each line item in a cart basically. Because of the nature of the page, I don't want to have a separate page to edit all the info. It seems this should work, but its likely I'm missing something through the tunnel vision I'm in now.
I should note, the form is for each line, I don't need it to submit all the forms, just the one.
Thanks
Change
datastring = $(formID).serialize();
to
var datastring = $('#' + formID).serialize();
You need to use a # prefix using the ID selector. Also - without the var keyword you polluting the global namespace for no reason.
Or even better ... you could replace
var formID = $(this).closest('form').attr('ID');
var datastring = $('#' + formID).serialize();
with
var datastring = $(this).closest('form').serialize();
Which finds the form and serialises it all in one go !!
Thanks to #MikeBrant for that suggestion.