Populating a grid via autocomplete and posting the results - model-view-controller

I have a view where I create a new company.
The company has a number of trades, or which 1 is a primary trade.
So when I enter the trades for that company, I select a trade via autocomplete, and this trade is added to a grid of trades underneath the autocomplete textbox. The grid contains the tradeId as a hidden field, the trade, and a radio button to indicate whether the trade is a primary trade and a remove button.
This is part of a form that contains other company details such as address.
Now I am wondering if I can use knockout and (maybe) jsrender to populate the grid without posting to the server?
When I have filled in the grid AND the other company details, I then want to submit the data to the controller post method.
Normally I use the Html helpers to post values to the controller, but I don't see how I can do that using knockout.

Yes you can use Knockout for this. If you have not checked the tutorials out yet then try this Knockout List and Collections tutorial. This should point you in the right direction. What you'll need to do is create a Trade object with observable properties and in a separate knockout view model create an observableArray to store trade objects. For information on posting to the server there are other tutorials in the same location.
function Trade(item) {
var self = this;
self.tradeId = ko.observable(item.tradeId);
self.tradeName = ko.observable(item.tradeName);
self.isPrimary = ko.observable(item.isPrimary);
}
function TradesViewModel() {
var self = this;
// Editable data
self.trades = ko.observableArray([]);
self.removeTrade = function(trade) { self.trades.remove(trades) }
self.save = function() {
$.post("/controller/action", self.trades);
}
}
ko.applyBindings(new TradesViewModel());

Related

How to reload kendo grid with filtered data?

I have a kendo grid, in which I have selected filter on one column, I am reloading the grid, I want the same filter to be there when grid reloads.
I am using the below code to reload the grid. It works, but it doesn't show the selected filter item checked. I checked IDR in the filter then reloaded the page, it shows 1 item selected but doesn't show IDR as checked.
function ReloadGrid() {
var grid = $('#gridId').data('kendoGrid');
grid.dataSource.read();
grid.setDataSource(grid.dataSource);
}
Well there is two way to achieve this.
One way is to save filters in database and second one is to use local storage as mentioned in comment.
I prefer second one, using local storage to save filters and load it upon read.
#GaloisGirl is pointing you in right direction.
Check this example again: Persist state
Basic usage of locale storage is to save some data under some name (key,value):
let person = {
name: 'foo',
lastName: 'bar'
};
let save = function (person) {
let personString = JSON.stringify(person);
localStorage.setItem('person', personString);
console.log('Storing person: ', personString);
};
let load = function () {
let personString = localStorage.getItem('person'); // <----string
let person = JSON.parse(personString); // <----object
console.log('Stored person: ', person);
};
let remove = function (name) {
localStorage.removeItem(name);
console.log('Removed from local storage!');
};
save(person);
load();
remove(person.name);
In kendo world you need to save current options state of grid in local storage, you can achieve that by adding button like in example or on the fly with change or with window.onbeforeunload or like in your example beforen reload grid.
You can check saved data under application tab in browsers, eg. chrome:
Hope it helps, gl!

Filling MVC DropdownList with AJAX source and bind selected value

I have view for showing Member details. Inside there is an EditorFor element which represents subjects taken by the member.
#Html.EditorFor(m => m.Subject)
Inside the editor template there is a Html.DropDownListFor() which shows the selected subject and button to delete that subject
I am using an Html.DropDownListFor element as :
#Html.DropDownListFor(m => m.SubjectID, Enumerable.Empty<SelectListItem>(), "Select Subject",
new { #class = "form-control subjects" })
The second parameter(source) is set empty since I want to load the source from an AJAX request; like below:
$.getJSON(url, function (response) {
$.each(response.Subjects, function (index, item) {
$('.subjects').append($('<option></option>').text(item.Text).val(item.ID));
});
// code to fill other dropdowns
});
Currently the html loads before the dropdowns are filled. So the values of all subject dropdowns are set to the default "Select Subject". Is there a way around this or is it the wrong approach?
Note: There are a number of dropdowns in this page. That's why I would prefer to load them an AJAX request and cache it instead of putting in viewModel and filling it for each request.
** EDIT **
In AJAX call, the action returns a json object containing dropdowns used across all pages. This action is decorated with [Output Cache] to avoid frequent trips to server. Changed the code in $.each to reflect this.
You can initially assign the value of the property to a javascript variable, and use that to set the value of the selected option in the ajax callback after the options have been appended.
// Store initial value
var selectedId = #Html.Raw(Json.Encode(Model.Subject.SubjectID))
var subjects = $('.subjects'); // cache it
$.getJSON(url, function (response) {
$.each(response, function (index, item) {
subjects.append($('<option></option>').text(item.Text).val(item.ID));
});
// Set selected option
subjects.val(selectedId);
});
However its not clear why you are making an ajax call, unless you are generating cascading dropdownlists which does not appear to be the case. What you doing is basically saying to the client - here is some data, but I forgot to send what you need, so waste some more time and resources establishing another connection to get the rest of the data. And you are not caching anything despite what you think.
If on the other hand your Subject property is actually a collection of objects (in which case, it should be Subjects - plural), then the correct approach using an EditorTemplate is explained in Option 1 of this answer.
Note also if Subject is a collection, then the var selectedId = .. code above would need to be modified to generate an array of the SubjectID values, for example
var selectedIds = #Html.Raw(Json.Encode(Model.Subject.Select(x => x.SubjectID)))
and then the each dropdownlist value will need to be set in a loop
$.each(subjects, function(index, item) {
$(this).val(selectedIds[index]);
});
If your JSON tells you what option they have selected you can simply do the following after you have populated your dropdown:
$('.form-control.subjects').get(0).selectedIndex = [SELECTED_INDEX];
Where [SELECTED_INDEX] is the index of the element you want to select inside the dropdown.

Firefox addon: how to grab data from webpage?

Purpose
I am trying to make a common answer database for a website form. The form is a description of computer hardware specifications, and I am trying to make it so that based on a model field, other fields are filled in automatically. The extension with have two buttons, "populate" which will based on the model field, check the database for a matching entry, and then populate data into the forms based on that. The second button being "save", which will take data in the fields and marry it to the model field and place it into the database.
Question
So, my main question is on interacting with the webpage itself, how do I grab data from the webpage, and then how do I make changes to fields?
So, my main question is on interacting with the webpage itself, how do I grab data from the webpage, and then how do I make changes to fields?
You can do this with a Firefox Add-on SDK Page-mod, click here for the documentation
Here is an example for getting data:
Example Page-Mod
/lib/main.js:
var tag = "p";
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "*.mozilla.org",
contentScriptFile: data.url("element-getter.js"),
onAttach: function(worker) {
worker.port.emit("getElements", tag);
worker.port.on("gotElement", function(elementContent) {
console.log(elementContent);
});
}
});
/data/element-getter.js:
self.port.on("getElements", function(tag) {
var elements = document.getElementsByTagName(tag);
for (var i = 0; i < elements.length; i++) {
self.port.emit("gotElement", elements[i].innerHTML);
}
});

Defining which field was changed in a grid

Is it possible to identify on a kendo UI grid which field was altered on a row edit?
Right now I am sending the entire row to the server that was changed. I would like to send
the request to the server to also include a variable holding the name
of the field that was edited.
Is something like that supported by kendo or
is there a work around for that?
This is not supported out of the box. However the grid API should allow this to be implemented. Check the edit and save events. In there you can listen to changes of the model instance which is currently being edit. Here is a quick example:
$("#grid").kendoGrid({
edit: function(e) {
e.model.unbind("change", model_change).bind("change", model_change);
}
});
function model_change(e) {
var model = this;
var field = e.field;
// store somewhere the field and model
}

MVC3 - display price based on product selection in form

I am sure there will be articles around this but I really don't know the correct name for it and having little success finding examples like mine.
I have a quote form where you have the ability to select a product and atributes of it. There are three dropdowns and based on the combination of the three, I have a table (with associated model/controller) that has a price. I want to display the price on the page but i must update as the selections are updated.
Setting the price from the get go seemed easy but then updating it based on dropdowns selected had me go in a tail spin of '"onSelectedIndexChanged()', javascript, AJAX, partial views and I simply confused myself.
I need a simple way to display price information on a quote form as they fill out the details (three fields control price). I did look at the music store demo but its slightly different and the shopping cart element which looked handy was grabbing data in a table so again got stuck.
Help always appreciated as ever.
Thanks,
Steve.
When one of the three dropdowns changes, I'd make an AJAX call to the server to get the price as a JSON object and use it to update the price input.
Example using jQuery to add the handlers and perform the AJAX operation.
var $priceControls = $('#control1,#control2,#control2');
$priceControls.change( function() {
$.getJSON( '#Url.Action("price","product")',
$priceControls.serialize(),
function(price) {
$('#price').val(price);
});
});
public class ProductController : Controller
{
public ActionResult Price( string control1, string control2, string control3 )
{
decimal price = ...lookup price based on control values...
return Json( price, JsonRequestBehavior.AllowGet );
}
}

Resources