How to simulate a Zend\Form submit without to display the form in Zend Framework 2/3? - zend-framework2

I have a complex nested (order) Zend\Form, that can be edited multiple times. Now I want to get the data and pass it later to a new form. (This way I want to implement a simple cloning mechanism.)
What already works is transforming the request data to JSON
if ($request->isPost()) {
...
if(isset($request->getPost()->toArray()['store'])) {
$this->storeFormJson(json_encode($request->getPost()));
}
...
}
...
and passing it to an empty form:
if ($this->params()->fromQuery('populate')) {
$formDataJson = $this->getFormDataJson();
$formDataArray = json_decode($formDataJson, true);
$parameters = new Parameters($formDataArray);
$request->setPost($parameters);
$request->setMethod(Request::METHOD_POST);
}
Alright. But it requires, that the user needs to call the edit form first, edit it (if needed), and send the data to the server (by submitting the form). Since the goal is to create clones on the fly, I need a way to simulate these steps.
How to get the data, that usually comes passed via form submitting, without a real submitting?

One thought is to create a new form F2 in which the fields are all hidden, populate F2 with values from your populated form F1, deliver the rendered F2 form to the client, and add client-side javascript that auto-submits the now-populated F2 form on page load. Just thinking out loud...

Related

Saving Cascading drop downs in MVC

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

Dealing with complex models in ASP.NET MVC

I have a model that looks like this:
Business
- Branch
- Phone(*)
- Phone Type
- Number
- Opening hours (*)
- Days in week
- Working period (*)
- From time
- To time
- Custom field (*)
- Name
- Value
- Address
- Address line
- City
- State
- Zip
- Yada yada
I created Editor Templates for each of the class types above.
I want to have a common Business editor template with a submit form that posts the entire structure to a single action and saves it, both for an existing or new entity.
Is Editor Templates the right approach? How do I submit the form along its entire downline?
How do I make Add and Remove buttons to add/remove phone numbers within the form?
How do I order items in the collection (i.e. I want to have arrows near each phone number so the user can move it up or down in the client list, then handle the saving on server, for that I already have the solution).
Bottom line, my issue is how to get the right values posted back to the server, and how to modify the inner collections on the client. Once the proper data is on the server in this way or another I'll know how to deal with it. My problem is the client side and the correct way of data submission.
Update
I saw this answer, which basically answers the 1st part of my question, tho the latter two still remain (add-remove-order buttons - manage collections on client).
My problem is not how to add/remove/reorder rows at the client's DOM, but how to modify the client data and then receive it in the server in the action the looks like this:
[HttpPost]
public ActionResult Save(Business business)
{
/// blah blah
}
Update
Here is how I try to shove in the new data:
View:
#Ajax.ActionLink("Add", "AddCustomField", new AjaxOptions { UpdateTargetId = "customFields", InsertionMode = InsertionMode.InsertAfter })
Action:
public PartialViewResult AddOpeningTimes()
{
var ot = new OpeningTimes();
ot.WorkingPeriods.Add(new WorkingPeriod());
var e = EditorFor(ot);
//just here for debugging, the values are both empty strings
e.ViewData.TemplateInfo.HtmlFieldPrefix = ViewData.TemplateInfo.HtmlFieldPrefix;
return e;
}
//this method is on the base controller:
protected PartialViewResult EditorFor<TModel>(TModel model)
{
return PartialView("EditorTemplates/" + typeof(TModel).Name, model);
}
The thing is the name for the appropriate fields are not enumerated as needed (Branches[0].CustomField[0].Key), instead, it's just Key.
As far as i know, there is no 'simple' way to do this.
Add button - you have to wire javascript that creates a part of form (eg. phone type select and phone text box) and set its id/name. Basically you find the last item in the form, which will have name of Phone[x].PhoneType, and set the values on new part of form to appropriate values with x + 1.
An option to avoid generating the part the form by yourself is to create a hidden 'template' and copy that. Then change id and name.
Remove button - if you simply deleted items from DOM, you would create gaps in the sequence and MVC doesn't know how to deal with that. One possible approach is to mark items in the form as deleted using a hidden field, then handling that on the server.
Reordering - I would add a property called Order to whatever needs this feature, then render it as hidden and change using javascript when reordering. You also have to set it appropriately when adding an item.
Useful properties in these situations are also: IsNew, IsUpdated - along with IsDeleted allow for relatively easy processing on the server.
Of course, if you have nested collections each needing add/remove/reorder functionality it will be kind of difficult to do and debug.
UPDATE
The action rendering the partial view can't know what the html prefix should be, because it doesn't have the context (that the parent is Branch object etc.).
If you want to use AJAX, i would recommend sending the html field prefix as a parameter (public PartialViewResult AddOpeningTimes(string htmlPrefix)). htmlPrefix could be Branches[0].CustomField[last_custom_field + 1].. It's probably the cleanest way to achieve what you want, even if it's in fact not very clean.

asp.mvc how do I submit mulitple forms?

I have an asp.mvc app the presents to the user different forms when they click on the next button - like a wizard. I do it this way so I can use JQuery to validate each form as the user progresses through them. i.e.
...
// use jquery validator to funk up the form validation
// user clicks the Next button ...
switch(currPageIndex) {
case 0:
if($('#form1'.valid()) {
$('#form1').hide();
$('#form2').show();
}
break;
}
...
However I can't use a single submit button to post the all the forms formcollection data back to my controller - if I do I only get back the one form that the submit button was in and not all of them.
Is there some magic icantation I can type in to get all the forms data sent back to the controller?
Presumably I can cruft up the data myself and send it back to my controller as a jason string, but I'm not sure if this is the best way.
Many thanks.
Wizard-like forms basically rely on a model which is kept on the server-side (in session or a database table) and kept updated.
For example, each post from the client you get back the model from session or database and then call UpdateModel() using the FormCollection which updates the model and the you can check if it is valid.
You can only submit one form at a time, however there are multiple ways around this in your scenario. When you change to the second form you could populate some hidden fields using javascript that would contain the information from the previous form. Then it would all be in the second form and you wouldn't have a problem getting the information.
You could also do it via ajax/json, but then you would probably want to do it with both of the forms data anyway.
In the end I just json'd up the form data and ajax'd it over to the controller, it works very well, nice and and clean to.
many thanks for the replies.
You can do that using $('#form1').submit() function, I don't think there is another way.

asp.net mvc: What is the correct way to return html from controller to refresh select list?

I am new to ASP.NET MVC, particularly ajax operations. I have a form with a jquery dialog for adding items to a drop-down list. This posts to the controller action.
If nothing (ie void method) is returned from the Controller Action the page returns having updated the database, but obviously there no chnage to the form. What would be the best practice in updating the drop down list with the added id/value and selecting the item.
I think my options are:
1) Construct and return the html manually that makes up the new <select> tag
[this would be easy enough and work, but seems like I am missing something]
2) Use some kind of "helper" to construct the new html
[This seems to make sense]
3) Only return the id/value and add this to the list and select the item
[This seems like an overkill considering the item needs to be placed in the correct order etc]
4) Use some kind of Partial View
[Does this mean creating additional forms within ascx controls? not sure how this would effect submitting the main form its on? Also unless this is reusable by passing in parameters(not sure how thats done) maybe 2 is the option?]
UPDATE:
Having looked around a bit, it seems that generating html withing the controller is not a good idea. I have seen other posts that render partialviews to strings which I guess is what I need and separates concerns (since the html bits are in the ascx). Any comments on whether that is good practice.
look at the ContentResult you can specify the mime type of what you return (text/html)
You could alternatively make a control that take a IEnumerable of whatever you put in the selectlist, and build it using the view engine. That way you keep the formatting of the html (in this case a list of options) into a view, and not in your code.
<%# Control Language="C#"Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Article>>"%>
<%foreach (var article in Model){%>
<option><%:article.Title %></option>
<%} %>
I think I would go for that second one
From what I understood, the jQuery dialog contains a form that, when submitted, will post to an action which updates the database with some information. You want to get the newly added database information and update the same form that was used to trigger the database update.
If that is the case, then I think the best clean and logical option is to return JSON serialization of the items to be put in the drop down right after you update the database. Then, using jQuery, you would clear the drop down and append option tags into it.
You can also write a new, seperate action that returns the JSON serialization of the database objects you need. You would have jQuery call another post to this action as a callback to your first ajax post (the one used to update the database).
Here is a quick snippet
public ActionResult UpdateDatabase(string something)
{
/// update the database
IEnumerable<Items> items = getItemsFromDatabase(); // or w/e
var vals = items.Select(x=> new { value = x.ID, text = x.Name }); // something similar
return Json(vals);
}
Personally, I would write a separate function that returns JSON. This ensure separation of concerns, and gives me a function I can use in many different places.
Returning a JsonResult with all the items is the most versatile and least-bandwidth intensive solution as long as you are happy to iterate through the list in jQuery and update your drop-down list.
Using a partial view is nice for HTML that you can .load(...) directly into your select, but less versatile.
I would go with the JsonResult.
In your Controller:
public JsonResult UpdateItem(string sItem)
{
// 1. Insert new item into database if not exist...
// {update code here}
// 2. retrieve items from database:
IEnumerable<Item> Items = GetItems();
// 3. return enumerable list in JSON format:
return new JsonResult{ Data = new {Items = Items, Result = "OK" }};
}
On client-side:
Iterate through Items array and add the items to your list.

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