Passing edited value contenteditable field from view to controller in Rails - ruby-on-rails

I am using Rails 3.1 to build a web form which, among other fields, contains a table whose cells can be edited. I require to save the text of edited cell in a database.
I am thinking of using HTML5 attribute 'contenteditable'. I can use the value of innerHTML of the cell . How can I pass this value to Rails controller (from the view)? Is it possible to use params to pass the data? Any suggestions?

HTML containers marked as contenteditable won't automatically be passed along to the server with a form submission, so you'll likely have to use javascript to pull the content out of those containers and pass them along in some fashion.
One strategy would be to add a handler to the form that fires before submit, which iterates over contenteditable containers and injects hidden form elements. The below example uses jQuery, but you could probably replicate the thought process without.
var form = $('#my_form');
var element;
$('[contenteditable=true]').each(function(){
element = $(this);
form.append($('<input/>', {
type:'hidden',
name:element.attr('id'),
value:element.html()
}));
});

Related

Passing DOM element to controller when using jquery autocomplete

I am using ASP.Net MVC and JQuery UI autocomplete.
I have a number of input-boxes set up in a table and I have this JavaScript code.
$('.searchfield').autocomplete({
source: '#Url.Action("AutoCompleteFunction")'
});
Which works perfectly. The controller reads from a database and returns a list of matches.
Now I have another column of fields that also need autocomplete. However, these autocomplete lists have to be dependent on what is already in the table.
How can I pass DOM elements to the autocomplete controller?
I have tried something like this. As long as I only pass a string it will work, but not when I try to pass it a DOM element.
$('.newsearch').autocomplete({
source: '#Url.Action("NewAutoCompleteFunction", new { firstParameter = "testing"})'.replace("testing", "'$document.activeElement.value'")
});

Pass multiple html parameter with BeginForm

I need to send parameters with values ​​in a BeginForm html.
Example:
# using (Html.BeginForm ("Create", "IncomeDeclaration", new {declarationAmount = document.getElementById ("element"). value}))
This value I can not get from the Model, as it is not found in the model.
I've tried several ways and nothing worked. If you could change the content of a ViewBag that'd be great.
I appreciate your support.
You can't mix and match Javascript (document.getElementById ("element")) with the C# form declaration. If you want a value submitted with the form, you should add a relevant form element inside the form declaration. If you don't want a regular form element (eg. a textbox), you can use a "hidden" input field. If you want, you can dynamically populate the hidden field using javascript.

ASP.Net Web Api + KnockoutJs + MVC4 - Tying it together

I am starting a new project, and keen to make use of the KnockoutJS + Web Api which are new to me, I have a good understanding of the Web Api, but Knockout is tough to get my head around at the moment.
This is my initial thoughts of how I want my app to work:
I have a standard MVC controller such as LeadsController
LeadsController has an Action called ListLeads, this doesn't actually return any data though, but just returns a view with a template to display data from Knockout.
The ListLeads view calls my api controller LeadsApiController via ajax to get a list of leads to display
The leads data is then mapped to a KnockoutJs ViewModel (I don't want to replicate my view models from server side into JavaScript view models)
I want to use external JavaScript files as much as possible rather than bloating my HTML page full of JavaScript.
I have seen lots of examples but most of them return some initial data on the first page load, rather than via an ajax call.
So my question is, how would create my JavaScript viewModel for Knockout when retrieved from ajax, where the ajax url is created using Url.Content().
Also, what if I need additional computed values on this ViewModel, how would I extend the mapped view model from server side.
If I haven't explained myself well, please let me know what your not sure of and I'll try and update my question to be more explicit.
I think your design is a good idea. In fact, I am developing an application using exactly this design right now!
You don't have to embed the initial data in your page. Instead, when your page loads, create an empty view model, call ko.applyBindings, then start an AJAX call which will populate the view model when it completes:
$(function () {
var viewModel = {
leads: ko.observableArray([]) // empty array for now
};
ko.applyBindings(viewModel);
$.getJSON("/api/Leads", function (data) {
var newLeads = ko.mapping.fromJS(data)(); // convert to view model objects
viewModel.leads(newLeads); // replace the empty array with a populated one
});
});
You'll want to put a "Loading" message somewhere on your page until the AJAX call completes.
To generate the "/api/Leads" URL, use Url.RouteUrl:
<script>
var apiUrl = '#Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Leads" })';
</script>
(That's assuming your API route configured in Global.asax or App_Start\RouteConfig.cs is named "DefaultApi".)
The knockout mapping plugin is used above to convert the AJAX JSON result into a knockout view model. By default, the generated view model will have one observable property for each property in the JSON. To customise this, such as to add additional computed properties, use the knockout mapping plugin's "create" callback.
After getting this far in my application, I found I wanted more meta-data from the server-side view models available to the client-side code, such as which properties are required, and what validations are on each property. In the knockout mapping "create" callbacks, I wanted this information in order to automatically generate additional properties and computed observables in the view models. So, on the server side, I used some MVC framework classes and reflection to inspect the view models and generate some meta-data as JavaScript which gets embeded into the relevant views. On the client side, I have external JavaScript files which hook up the knockout mapping callbacks and generate view models according the meta-data provided in the page. My advice is to start out by writing the knockout view model customisations and other JavaScript by hand in each view, then as you refactor, move generic JavaScript functions out into external files. Each view should end up with only the minimal JavaScript that is specific to that view, at which point you can consider writing some C# to generate that JavaScript from your server-side view model annotations.
For the url issue add this in your _Layout.cshtml in a place where it is before the files that will use it:
<script>
window._appRootUrl = '#Url.Content("~/")';
</script>
Then you can use the window._appRootUrl to compose urls with string concatenation or with the help of a javascript library like URI.js.
As for the additional computed values, you may want to use a knockout computed observable. If that is not possible or you prefer to do it in .Net you should be able to create a property with a getter only, but this won't update when you update other properties on the client if it depends on them.

ASP.NET MVC Ajax: How to update an Ajax.ActionLink itself on-click

I have a page that displays a list with a of elements with a large number of elements, each of which has a boolean property, representing an Enabled and a Disabled state.
I need to provide the user with a link for each list item, and the link text must show the opposite status (so if the item is enabled, the link text must display 'Disable').
When the user clicks the link for a Disabled, the corresponding link text for the item must change to 'Enable' (and vice versa).
I would like to NOT reload the entire list for each click, just the text of the ActionLink itself, so my question is:
Is it possible to update just an ActionLink itself when the user clicks the link, or do I have do handle this using custom javascript?
As far as I remember, you can add HTML attributes to the "a" tag by newing up an anonymous class as the last param on most overloads.
Off the top of my head this can be written like the following:
Html.ActionLink("Name", "Action", "Controller", new { #class = 'updateId' });
(You may be able to do this with an ID which would be preferable over a class - if not just use a unique class name to avoid updating multiple items.)
Then you can use javascript to access the class "updateId" and change the inner html.
In the case of jQuery:
$("a.updateId").html("NewName");
This can be done with a custom user control contained within the element to update. A writeup of the solution can be found here. No custom client-side scripting is necessary.

ASP.NET MVC- submitting a client side created collection

I am using javascript to append user selections to a list. When user is done , which is the best way to go:
1: create index for the list and submit as model in a form to the controller?
2: create hidden element and use javascript to append values and submit as actionlink? (not sure how to tell actionlink the value here)
3: wrap form block around the hidden element only and submit string as model?
other?
I think the easiest way is to put some form of your list to the hidden field (type=hidden) and it will be automatically submitted with form and accessible on server under the name you gave it. So main reasoning here is the way you going to process these data on the server side.
First of all, Scott Hanselman has a good post about model binding to arrays, collections, etc.
In my opinion you shouldn't use second way because this will be a vulnerability ( description of CSRF).
In order to use collections binding you'll need to wrap a form around a list and submit it (note, this form will submit only selected values in this list but you may select them all before submit) or to create a map of values and submit it via javascript (for jQuery - $.post(url, data, callback)) or to add all pairs of name&value to some hidden element of a form and submit it.

Resources