So, I'm working on this grails application to create a web dashboard. So far, I have created a controller that queries metrics from my database and renders it as a JSON file, which I feed to d3 and other javascript libraries on the front end gsp file.
My question is this: I have a certain drop down menu on my front end as follows:
<select onchange="loadData()" id="metric" class="dropdown">
<option value ="sales">Sales</option>
<option value ="visits">Visits</option>
</select>
And my corresponding controller, in its simplest form, has the following actions:
(Importing grails.converters and groovy.sql.sql)
def dataSource
def listJson = {
def sql = new Sql(dataSource)
def rows = sql.rows("select date_hour, total_revenue as sales, visits from table")
sql.close()
render rows as JSON
}
The problem now is, I have a bunch of drop down menus, and quite a lot of options in each, for each of which, if I did as above, I would have to create a new json file for d3 to use. Instead, can't I somehow insert the value of the option from the select element above, into the sql statement in the controller?
Something like the one below, but I don't know if it's possible, and if it is, the right syntax. I'm using grails 2.3.4 right now.
def listJson = {
def sql = new Sql(dataSource)
def rows = sql.rows("select date_hour, total_revenue as sales, ${index #metric} from table")
sql.close()
render rows as JSON
}
where index is my index.gsp file (where the select option is), and #metric, the id of the element.
Thanks in advance!
You can get the value of the select from params in your controller. For example:
def listJson = {
def metric = params.metric
// build query...
def query = "... ${metric} ..."
}
However, I'd advise against building a SQL query like this. Any time you accept user input as part of a SQL query it provides a huge opportunity for SQL injection attacks. Why not use a higher level database abstraction like GORM? Also note that groovy uses different parameter expansion in SQL queries than regular strings to generate for PreparedStatements. You'd need to write your example like this: sql.rows("select date_hour, total_revenue as sales, " + metric + " from table")
Finally, while it depends on how you're submitting the request in loadData(), the usual convention for HTML input elements is to submit the value with the element name attribute as the key, not the id.
Related
I would like to make a query given the id of my book in javascript and not fetch all the books from the database, for example:
I usually do it like this:
In my book controller, I make a query the collection of books and then pass it to the view through a variable:
# books_controllers.rb
before_action :set_books
...
def set_books
#books = Book.all # here is my books collection
end
In my form view I define a variable to store the collection of books, in a books_info
variable:
#books/form
javascript:
let books_info = #{#books.to_json.html_safe};
And finally, the collection of books is scanned and compared with the id that the client gives me to find the specific information of said book.
Array.from(books_info).forEach((element, index) => {
if (element["book_id"] === client_book_id){
new_book_id = element;
}
});
The problem with doing all that is that I compromise all the book information in views
Simply what I am looking for is given the id of the client (client_book_id) to do this in javascript
javascript:
let client_book_id = #{Book.find(´client_book_id´).to_json.html_safe} # This not work but I try to got it.
If you could help me I would be very grateful.
Add the book ID to the query string of the URL, e.g. ?book_id=123
The Rails controller reads the ID as e.g. params[:book_id]
The controller sets an instance variable, e.g. #book = Book.find(params[:book_id])
The Rails view sets the JS variable using .to_json as already shown in the question
This is just one application design, good for beginners. Other designs include XHR (intermediate) or GraphQL (advanced).
I have two tables which are claim table and claim_type table. Currently, I want to get the name of the claim inside the claim_type table. So, from the table Claim, we will get which type of claim (in the form of id) and after that, we can get the name of the type. I already have queried it inside MySQL workbench like this.
SELECT claim_types.name, count(*), sum(amount) FROM myteduh_v1.claims
join claim_types on claim_type_id = claim_types.id
group by claim_type_id;
When I post to the PHP, which to query it is like below. It turns out some error.
$ClaimsType = ClaimType::pluck('name')
->count()
->join('claim_types','claim_type_id','=', 'claim_types.id')
->groupBy('claim_type_id')
->get();
dd($ClaimsType);
$Claims_pie_chart = Charts::create('pie', 'highcharts')
->title('Total Claims Based On Type of Claims')
->labels(['$ClaimsType'])
->values([15,25,50])
->dimensions(1000,500)
->responsive(true);
After that, I want to insert the $ClaimsType into the labels variable to be pie chart labels. The question is, is it wrong the way I query the database inside the PHP controller?
If you want to use aggregation in one query, you should use DB:raw() in select
$ClaimsType = Claim::select(['claim_types.name', DB:raw('count(*)'), DB:raw('sum(amount)')])
->join('claim_types','claim_type_id','=', 'claim_types.id')
->groupBy('claim_type_id')
->get();
now you can use ->toSql() instad of ->get(), and you will see that query is same as yours raw query.
I need to be able to export a HTML table to CSV. I found a snippet somewhere; it works but not entirely how I want it to.
In my table (in the fiddle) I have hidden fields, I just use quick n dirty inline styling and inline onclicks to swap between what you see.
What I want with the export is that it selects the table as currently displayed. so only the td's where style="display:table-cell". I know how to do this in normal JS.
document.querySelectorAll('td[style="display:table-cell"])');
but how can I do this using the code I have right now in the exportTableToCSV function?
(sorry but the text in the fiddle is in dutch as its a direct copy of the live version).
The fiddle:
http://jsfiddle.net/5hfcjkdh/
In your grabRow method you can filter out the hidden table cells using jQuery's :visible selector. Below is an example
function grabRow(i, row) {
var $row = $(row);
//for some reason $cols = $row.find('td') || $row.find('th') won't work...
//Added :visisble to ignore hidden ones
var $cols = $row.find('td:visible');
if (!$cols.length) $cols = $row.find('th:visible');
return $cols.map(grabCol)
.get().join(tmpColDelim);
}
Here's how i solved it. Decided to step away from a pure javascript solution to take processing stress off the client and instead handle it server side.
Because i already get the data from the database using a stored procedure i use this to just get the dataset again and convert it into an ViewExportModel so i have a TotalViewExport and a few trimmed variations (reuse most of them) based on a Selected variable i fill a different model.
Added to the excisting show function to update a Selected variable to keep track of the currently selected view.
When the user clicks Export table to excel it calls to the controller of the current page, IE. AlarmReport (so AlarmReportController) and i created the action ExportReports(int? SelectedView);
In addition i added CsvExport as a manager. This takes data results (so c# models/ iqueryables/ lists/ etc). and puts them into a Csv set. using the return type BinaryContent one can export a .csv file with this data.
The action ExportReports calls the stored procedure with the selectedview parameter. The result gets pumped into the correct model. this model is pumped into the CsvExport model as rows.
The filename is made based on the selected view + What object is selected + current date(yyyy-MM-dd). so for example "Total_Dolfinarium_2016-05-13". lets
lastly the action returns the .csv file as download using the BinaryContent Returntype and ExportToBytes from the CsvExport
The export part of this action is programmed like so(shortened to leave some checks out like multiple objects selected etc)(data and objectnames are gathred beforehand):
public ActionResult ExportCsv(CsvExport Data, string ObjectName, string Type){
var FileName = Type + "_" + ObjectName + "_" + DateTime.Now.ToString("yyyy/MM/dd");
return BinaryContent("text/csv", FileName + ".csv", Data.ExportToBytes());
}
I have a website where info of registered member from various countries and states are collected. On my search form, I have 3 fields; Country, State and Sex.
I listed all the countries of the world in my search (as a dropdown), but the state field is empty. Want I want is that once a visitor select a country, i want only the states of that country which registered members have are in my database to be pulled into the state field, instead of all the state of that country.
Eg 3 members from USA are from New York, New Jersey and Georgia. On selecting USA in the country dropdown, only these 3 state should appear under the state instead of the 50 states in america.
You would need to do a script, for example, in php(or any server side language), that does the query, it would look like:
$countryId = $_POST['countryId'];
$sql = "SELECT fields FROM states WHERE countryId = $countryId";
$result = .... etc;
returning an json object for example to the main page.
And from the main page you should do a Ajax request to the php page, getting the json object returned depending on your option selected and populating the next field.
You could have a look at jQuery framework as at least I, find easier than using raw javascript.
You could pull the the states of the registered members from your database using php or any server-side language you are using. Then you can use AJAX to get the states as an xml or a JSON object. You can the use the members of the object to populate the dropdown.
Example sql query string to get states of registered users: Select state From user_details WHERE country = 'USA'. This should return the states (probably in an array);
Example PHP code that will be retrieved by an AJAX call: $reply = {states: [NJ, NY, AZ]}.
Example JS code to parse the above reply: var reply = JSON.parse(serverReply);
var states = reply.states;
. I hope this helps
I wanted to develop a Django app and one of the functionalities I'd like to have is dynamic drop-down lists...specifically for vehicle makes and models...selecting a specific make will update the models list with only the models that fall under that make....I know this is possible in javascript or jQuery (this would be my best choice if anyone has an answer) but I don't know how to go about it.
Also, I'd want the make, model, year and series to be common then the other attributes like color, transmission etc to be variables so that one needs only enter the make, model, year, and series only for a new vehicle. Any ideas would be highly appreciated.
The 3 things you mention being common, make, model, year, would be the 3 input values. When given to the server, an object containing the details would be returned to the calling page. That page would parse the object details (using JavaScript), and update the UI to display them to the user.
From the Django side, there needs to be the facilities to take the 3 inputs, and return the output. From the client-side, there needs to be the facilities to pass the 3 inputs to the server, and then appropriately parse the server's response.
There is a REST api framework for Django that makes it rather easy to add the "api" mentioned above -- Piston. Using Piston, you'd simply need to make a URL for that resource, and then add a handler to process it. (you'll still need to skim the Piston documentation, but this should give you an idea of what it looks like)
urls.py:
vehicle_details = Resource(handler=VehicleDetails)
url(r'^vehicle/(?<make>.*)/(?<model>.*)/(?<year\d{2,4}/(?P<emitter_format>[a-z]{1,4}), vehicle_details, name='vehicle_details'),
handler.py:
class VehicleDetails(BaseHandler):
methods_allowed = ('GET',)
model = Vehicles #whatever your Django vehicle model is
def read(self, request, *args, **kwargs):
# code to query the DB and select the options
# self.model.objects.filter()...
# Build a custom object or something to return
return custom_object
This simply sets up the url www.yoursite.com/vehicle/[make]/[model]/[year]/json to return a custom data object in JSON for jquery to parse.
On the client side, you could use jquery to setup an event (bind) so that when all 3 drop downs have a value selected, it will execute a $.get() to the api URL. When it gets this result back, it passes it into the Jquery JSON parser, and gives the custom object, as a javascript object. That object could then be used to populate more drop down menus.
(Big warning, I just wrote the following off the top of my head, so it's not meant to be copy and pasted. It's just for the general idea.)
<script type="text/javascript">
// On document load
$(function() {
$('#dropdown_make').bind('change', checkForValues());
$('#dropdown_model').bind('change', checkForValues());
$('#dropdown_year').bind('change', checkForValues());
});
function checkForValues() {
if ($('#dropdown_make').val() && $('#dropdown_model').val() && $('#dropdown_year').val())
updateOptions();
}
function updateOptions() {
url = '/vehicle/';
url += $('#dropdown_make').val() + '/';
url += $('#dropdown_model').val() + '/';
url += $('#dropdown_year').val() + '/';
url += 'json/';
$.get(url, function(){
// Custom data object will be returned here
})
}
</script>
This is uncanny: Dynamic Filtered Drop-Down Choice Fields With Django
His question:
"Here is the situation: I have a database with car makes and models. When a user selects a make, I want to update the models drop-down with only the models associated with that make. ... Therefore I want to use Ajax to populate the data."
You're not the same guy? :)