I have a side bar currently in ul and li elements seen in the picture below.
And I have three charts on the right side of it.
Each chart has its own REST web-service to update its data.
When I click on the side bar items I want to update those charts. (Through Ajax calls)
What is the high-level design for this? For example do I need link_to on my li elements? What to put in there? How to pass params? How to make the calls? Any gems that makes the life easier?
Some high-level and even lower level design is appreciated so I know where to begin from.
This is more an AJAX question than a rails question.
You need to add click handlers on the li's (jQuery is probably the easiest way to go) and have those send an AJAX request to your REST endpoints for the charts. Depending on your setup, I would recommend having those endpoints return the data you're looking for in JSON format and then updating the values in the charts (maybe go crazy and use d3js to draw them).
I'm guessing the REST endpoints need a physician_id or something in order for them to return the correct data, and you'll need to get this from somewhere. I usually just add the id as a data attribute on the element.
<li class="js-physician" data-id="<%= physician.id %>">Physician X</li>
I'm assuming you're iterating over a #physicians collection to get the list.
Then for your js do something like
$(document).on('click', '.js-physician', function(e) {
var physician_id = e.target.getAttribute('data-id');
params = { // this is your AJAX object
type: 'GET',
url: '/some_rest_url?physician_id=' + physician_id,
success: function(data) {
// update the charts with the returned data
},
error: function(jqXHR, textStatus, errorThrown) {
// handle error
}
};
$.ajax(params);
});
so all you have to do then is set up your callback handlers and make sure you're sending the right data.
Related
My web page uses Jquery to overload a screen. In this overlay, the user can type some detail and click the submit button.
What I'd like to do is, when the user clicks on submit, the overlay doesn't disappear (as it would do with a page refresh), but a message appears, such as "all done"
The question I have though, is, what is the correct return type? I've gotten myself into a muddle I'm sure.
I tried to make the return type string, and return the string. Sadly, this redirected me to a page with the string value.
I then thought I would need to return a ContentResult() with return Content(myString). The result was the same as returning a string.
I then tried to return void, and simply in my controller use ViewBag.Status ="All done"; This now takes me an empty page.
How can I make the message show "All done" or "Complete" without losing the state? Am I trying to do the impossible without Ajax or similar?
Yes, you are trying to do the impossible. When a controller action gets hit on a synchronous request (e.g. a form submission) you are always going to get a full-page load. That's exactly what a synchronous request is. In effect, the "refresh" has already happened before your action code even runs; the return type of the action is irrelevant. For partial updates, you need an asynchronous request, which means AJAX.
The typical approach to this would be to load in your overlay and then, submit the form from the overlay via AJAX, return a partial view and target a container with jQuery. You'd typically create some kind of generic wrapper for your overlays that will do this for all form posts within any overlay.
Alternatively, you could look at returning JSON and using a JavaScript templating engine like Handlebars to populate the view.
Either way it's a good idea to look at wrapping all of this up in some "generic" JavaScript code that will do the same thing for form posts in all of your overlays; then you can stop worrying about the client-side code and focus on just returning the right thing from your controller actions.
If you want to do that WITHOUT ajax, you will need to return the whole underlaying page again, including the popup in a visible state.
What you (probably) SHOULD do is to use ajax and return a json result. Something like this jQuery solution:
$(document).on('click', '[type="submit"]', function(){
var $form = $(this).closest('form');
$.ajax({
url: $form.action,
type: 'post',
data: $form.serialize(),
success: function(response){
// write success message to user
}
});
});
I have cascading dropdowns in my MVC partial view. DD1 drives the values in DD2. When I select DD1 I want DD2 to be populated with, based on a DB table, the correct values based on DD1's value.
My thought was to make DD2 a partial view and nest in my form. Then, with ajax, I can tell the partial view to refresh and pass it the value of DD1.
The problem is, when I submit the whole view (with both DD1 and DD2 and a bucnh of other stuff, how do I get the value that is in DD2?
I'm trying to solve this problem using MVC, rather than triggering a javascript function on change of DD1 to make a JSON call to get the options and then using javascript to modify DD2 to the correct values.
How should I do this?
How big are your value sets for each drop down?
I was attempting to do this same thing a few years ago. DD1 was United States and Canada, and DD2 was the associated States and Provinces. If your data set is relatively small, you're better off just putting all the select list markup for both cases in the page, and then swapping it out with javascript (jQuery). You'll be saving yourself the request round trip, regardless of whether you go ajax or a full page refresh.
If the data set is large and it doesn't make sense to put all values in the markup, and you want to use MVC views instead of modifying the DOM with an ajax call, then just refresh the entire page. If you want to go ajax, then just modify the DOM with jQuery; you don't need a partial view to accomplish this.
You are going to have to use javascript unless you want to do an entire page postback. For this type of thing, javascript/ajax is the way to go. I personally had a hard time when I switched to MVC having to accept that all this business logic was happening outside of the MVC model. But in the end, it's whatever makes the website work best (user doesn't see your code and know how pretty it is).
Anyway, partials won't work either unless you post the whole page since without using javascript, the partial is rendered as part of that page/form.
I would just add a onchange event to the first dropdown that triggers a json call to a method in the same controller...something like
...jquery...
$("#mydropdown").change(function() {
$.post("/Controller/DropdownChangedJSON", { firstdropdownvalue: $("#mydropdown").val() }, function(data) {
$("#seconddropdown").empty();
// loop through "data" to populate dropdown
}); //post
}); //mydropdown_change()
and in your controller:
public JsonResult DropdownChangedJSON(string firstdropdownvalue) {
//get results
List<datamodel> myarray = //something
return new JsonResult { Data = new { success = true, rows = myarray } };
}
hope this helps
I have a web application that uses VB.NET MVC for the server side code. I set up the client side JavaScript to easily send and receive data to the server Controller functions. Basically what I did was create a JavaScript "request" object that uses Ajax to call a controller function and pass in parameters. I let MVC do all of the serialization for me. Then the controller function returns a JSON, usually with a block of HTML as a string. Since I am handling all of the ajax calls in one place, I can't figure out a good way to handle the responses. When the ajax response comes back, I have no way of knowing which request it came from. The website has a lot going on so the responses all need to be handled differently and all return different data.
Right now what I do is in the controller function I send back some key along with the block of HTML, then in the ajax complete function I check for all of these specific keys. Doing it this way makes the javascript code difficult to manage.
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
if (data.Foo) {
Foo(data);
} else if(data.Bar) }
Bar(data);
}
});
I am having trouble researching this because I don't know which keywords to look up. I think I'm going to try and do something where I call the function names dynamically in the ajax done function, but I was wondering if there are any existing libraries or code examples that do larger scale ajax request functions like this.
Maybe the problem comes from the idea of "doing all the stuff in one place". I can imagine that it will be very difficult to maintain your code once you have 40 chained if...else if... in one method. Maybe splitting things up a bit wont hurt after all.
Anyway, one way of doing it the way you want it would be instead of passing a key, passing the name of the javascript function as a delegate. Then call window[data.funcName](data); in done().
Say your json is
{
foo: "bar",
funcName: "DoMyFoo"
}
This is how your call would look like :
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
window[data.funcName](data);
});
function DoMyFoo(d){
//Do your specific stuff here
alert(d.foo);
}
See this question How to execute a JavaScript function when I have its name as a string for info and examples.
Edit: If your functions lies within an object instance instead of the global namespace, say obj, you can call it the same way with obj['myFunction'](args)
I am having some issues around the patterns needed to bring my application into the WebApi + Knockout world. The following scenario has thrown be a bit.
I have a very basic grid partial view (_grid.cshtml). It uses a GridViewModel, which only has a QueryID. The Grid partial passes the QueryID using Ajax (which is defined in the ko ViewModel) to a WebApi method which returns a collection of objects in JSON. I then use knockout to bind the columns of the grid based on the returned JSON, and then loads the rows in.
This all works fine, but I'm uncertain if this is the correct approach.
// When the query is changed update the grid data.
self.selectedQueryID.subscribe(function (newQuery) {
self.SelectQuery(newQuery.ID());
});
// Execute the query and set the results as the rows of the table
self.SelectQuery = function (queryID) {
$.ajax({
url: '/api/Query/Execute?ID=' + queryID,
type: 'POST',
contenttype: 'application/json',
success: function (result) {
self.gridData(result);
}
});
};
The complexity comes when I have another partial view which is a list of available Queries that a user can choose from. This partial view sits adjacent to the grid partial view. I want to be able to somehow send the clicked query across to the grid so it can then shoot another ajax request off to get the data of the new query. I know this is completely the wrong way to think about an MVC application, but I just don't know enough about WebApi.
#Html.Partial("~/Views/Shared/_Grid.cshtml", Model.GridViewModel)
#Html.Partial("~/Views/Shared/_Queries.cshtml", Model.User)
This is all in an effort to implement some sort of default query for the grid, then give the user the option to select other queries.
I have also started looking into Backbone and Knockback but don't know (enough about them or) if this is the right direction.
I have a dropdown of countries, and an address form. Depending on the country selected, I want to hide/show certain fields. I'm quite new to MVC and MVC3, what is the best way to do this?
I have on the page a 'DropDownListFor' that populates correctly. When this changes, I imagine I need to ask the server which fields to show/hide. I could perhaps put some JQuery into a change event that calls a method, and it returns some json saying visible:true for each field, but I don't know if that's ideal or even how to implement it (possibly $.ajax or something).
Any ideas?
Edit: I should add the hard part of this is asking the server what fields to show for each country as there are many countries and the possibilities are all stored in the database. I am accustomed to webforms not MVC so I would ordinarily postback and have serverside logic, but this isn't an option with MVC afaik...
I have deleted my first answer as it was irrelevant.
With MVC3 you can send an AJAX request to any method.
In HomeController.cs:
public List<string> GetFieldsToShow(string id)
{
// if you routing is left to default, the parameter passed in will be called 'id'
// Do what you gotta do...
List<string> listOfFieldsToShowBasedOnCountry = GetList(id);
return listOfFieldsToShowBasedOnCountry;
}
And in the AJAX call, something like...
$.ajax({
type: 'POST',
url: '/Home/GetFieldsToShow/' + valueOfSelectedDropDownItem,
/*etc...*/
success: function(data){
$(data).each(function(){
$('#' + this).show();
}
}
});