How to rerender part of page after ajax submit of form in Lift (Scala) - ajax

this is probably a stupid question but I cannot figure out how to do it.
So I'm new to Scala/Lift and I read the ajax form chapter in http://simply.liftweb.net/index-4.8.html#toc-Section-4.8 but the "RedirectTo" in the example does not seem to be very "ajaxian" to me. Often in case of submitting a form via ajax, you would just partially rerender the same page, right?
So that's what I'm trying to do and am completely failing right now.
How do I let Lift rerender just a part of the same page after I submit the form via ajax?
Any hints would be appreciated. Thanks.
Basically, what I have looks like this:
<div id="main" class="lift:surround?with=default;at=content">
<h2>Welcome to your project!</h2>
<div class="lift:Test">
<div>
<form class="lift:form.ajax">
<fieldset>
<label for="name">Name:</label>
<input id="name" name="name" type=text>
<p></p>
<input id="save" type="submit" value="Save">
</fieldset>
</form>
</div>
<div>
<span id="theName">Name</span>
</div>
</div>
</div>
class Test {
def render = {
var name = ""
def process(): JsCmd = {
Thread.sleep(500)
S.notice("Entered name is: %s".format(name))
Noop
}
"#theName " #> "This shall be updated with the name given in the form above" &
"#name" #> (SHtml.text(name, name = _) ++ SHtml.hidden(process))
}
}
How would I update "theName" when submitting the form?

Have a look at http://lift.la/shtmlidmemoize-simple-ajax-updating (Example Code). There is SHtml.memoize and SHtml.idMemoize which automatically caches the HTML code. Not sure why it is not used in this example in the Simply Lift book.

You have a 2 step form right? The above poster is correct.
Save your transformation in a RequestVar.
in your above example, the method you want to save is render, so 1st memoize the transform:
private def renderTest= SHtml.memoize { render }
Then, you can save this memoized transformation in a RequestVar (lasts for 1 request), or maybe a TransientRequestVar depending on your needs.
private object testTemplate extends RequestVar(renderTest)
When you want to replay the transform, from an ajax event - testTemplate.is.applyAgain.
I might have misunderstood the original question, b/c if you want to do a 2 step form, you don't really need the memoize. The memoize is if something changes on your current form, and you want to update it via an ajax event, i.e. on click or on change, b/c normally the form wouldn't update unless you did an ajax submit.

Related

Laravel: Two form with one submit button

I want to submit two form into two url and want to submit from two another functions of a Controller.
<form method="post" url="{ '/url1' }">
</form>
<form method="post" url="{ '/url2' }">
</form>
<button type="submit">Submit</button>
Is it possible to do without AJAX??
Simple answer : no, without ajax you can't send two requests.
Complicated answer: unless the first one carries the data for both then in the first response, it sends the second request with the data for it. Which is so complicating things, you should just do it in one request.
You can use jQuery to submit both forms like in the example below:
First of all, add an id to your button like this
<button type="submit" id="submitBtn">Submit</button>
Add ID to your forms:
form method="post" id="form1" url="{ '/url1' }">
form method="post" id="form2" url="{ '/url2' }">
I don't know what is wrong with the stakoverflow editor, that is why i deleted the "<" sign.
3. Now handle the jQuery click event:
$(document).ready(function(){
$('#submitBtn').on('click',function(){
$('#form1').submit();
$('#form2').submit();
});
});
You could give the forms different ids but same action.
Then in the controller called by the submit button, let IF statements check for the form ids and return the respective view desired eg
$requests = $request->all();
$form_Id = $requests['form1_Id'];
if($form_Id != 'id_of_first_form') {
return view('url2');
}else{
return view('url1');
}
If you have a main page form and a modal form and you wanna submit both in order, you can do it with javascript like this
// cause double submits at once
function doubleSubmit()
{
$.post($('#recordPaymentForm').attr("action"), $('#recordPaymentForm').serialize(), function(response) {
$('#submitEditOrderButton').trigger('click');
});
return false;
}
Leave your main page form as it is and change your modal form on submit attribute like this
<form id="recordPaymentForm" method="POST" action="/orders/{{$order->id}}/payments" onsubmit="return doubleSubmit(event)">
Please not that we first submit modal form and then we trigger on click event of submit button (submitEditOrderButton) on the main page. In this example, we first submit payment form and then we trigger click event of main page form which cause a form submit on the main page.

UWP get form in webviewer returning 'about:blank' rather than form values

We have a mobile app which shows an html page with some javascript in a webviewer.
In this page we have a form. IT looks something like:
<form method="get" action = "" id="mainform">
<input name="EXAMPLE_NAME" id"EXAMPLE_NAME" placeholder="" type="text" maxlength="35"/>
</form>
So far so good. The user is able to view this input and fill it in with data. They then press a button on the xaml page which calls a function that does:
Browser.Eval("submitMainForm()")
In the javascript on the page we have that function, which looks like:
function submitMainForm() {
var x = document.getElementById("mainForm").submit();
}
Back in the C# code we have handlers for the resulting navigation. They look like:
async void OnNavigating(object sender, WebNavigatingEventArgs e)
{
and
void OnNavigated(object sender, WebNavigatedEventArgs e)
{
This works well in iOS and Android. We get the WebNavigatingEventArgs in the handler, and the value from the field that we are showing in the webviewer (inside of mainform) are stored in there.
So, for example, e.Url in the OnNavigating and OnNavigated handlers would look something like:
"file:///storage/emulated/0/Android/data/com.example.exampleapp/files/Example.html?EXAMPLE_NAME=Test"
We parse this string to get the values we care about (Test, in this case), and all is well.
On UWP, however, things work a lot less well. On Navigating is never called at all, and the call to OnNavigated just has "about:blank" stored in its WebNavigateEventArgs url value.
Does anyone know what might be going on here, and/or have a way that I can fix it? I need a way to get the results from my call to the get form as I do in the other 2 platforms, rather than "about:blank". Ideally, I'd also like to get the OnNavigated call, but the important thing is the data.
Thanks for your assistance
For html form submitting, you need add the action url that used to received parameter. For example:
<form id="Myform" action="HomePage.html">
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
<input type="submit" value="Submit">
</form>
When you invoke submit, the firstname lastname field will be sended to HomePage.html page. I create HomePage that Build Action is Content in native uwp project.
Please note you could not create html in forms project. Otherwise the webview could get navigate to the right url.
This is code sample please check.

Code Igniter- forms

I have a view. In this view
<form id="validate'>
some fields are here.
</form>
<form>
</form>
<input type="Submit" value ="Submit" >
Now submit button will not work since it is in below and I want form id="validate" to get posted.
Since I have to do some JS validation on form id="validate" this will also not work.
My question here is how to post the form and validate the form. Let em know, I f I am not clear here.
It is easy with JQuery if you are using it
<form id="validate'>
some fields are here.
</form>
var validation = $('#validate').validate();
if validation is successfull
$('#validate').submit();
else
//do something else

Validation of dynamic created form (AngularJS)

I try to made nested form with validation. All works fine, but when I remove one of nested form, validation continue to use removed form. I made jsfiddle example http://jsfiddle.net/sokolov_stas/VAyXu/
When example runs, form are valid. If click "+" button, nested form will be added and valid will be false. Then click "-" button, and valid will be false all the same.
The question is: How to remove dynamic created form from validation processing.
Well, for one thing, a <form> inside of a <form> is not valid HTML.
Second, you're not supposed to be doing DOM manipulation from inside the controller. The controller is for "business" logic. See the section on controllers here
For what you're doing, you'd probably be better off using one form, with an ng-repeat inside of it, and adding additional elements to an array:
<form name="myForm" ng-controller="FormCtrl" ng-submit="doSomething()">
<div ng-repeat="item in items">
<input ng-model="item" type="text" required/>
</div>
<a ng-click="addItem()">+</a>
<a ng-click="removeItem()">-</a>
<button type="submit">Submit</button>
<div>Form valid: {{myForm.$valid}}</div>
</form>
and the controller:
function FormCtrl($scope) {
$scope.items = [];
$scope.addItem = function() {
$scope.items.push(null);
};
$scope.removeItem = function() {
$scope.items.pop();
};
$scope.doSomething = function () {
//your submission stuff goes here.
};
}

Grails WebFlow with Ajax

I am trying to transition to next state of a WebFlow using Ajax requests. But it stays in the same state and returns the GSP as response for that state while I am expecting the GSP for the next state.
Following is the WebFlow code:
def gettingStartedAjaxFlow = {
flow1 {
on("next") {
println "flow1"
}.to("flow2")
on("skip").to("flow2")
}
flow2 {
on("next") {
println "flow2"
}.to("flow3")
on("skip").to("flow3")
}
flow3 {
on("next"){
println "flow3"
}.to("finish")
on("skip").to("finish")
finish {
redirect(action:"index")
}
}
}
Following is the Ajax call I am making for the state transition:
$.ajax({
type: "POST",
url: "/UN/user/gettingStartedAjax",
success: function(data) {
$("#wizardDiv").html(data);
}
});
The GSPs for each state (flow1, flow2, flow3) contains a a code fragment having remoteForm & required next and skip submit buttons to transition to next state and as a result update the "wizardDiv" div. Following is the GSP fragment for flow1 state:
<g:formRemote name="flow1Form" url="[controller:'user', action:'gettingStartedAjax']" update="wizardDiv">
<p>You are in flow 1</p>
<g:submitButton name="next" value="Next Flow" />
<g:submitButton name="skip" value="Skip Flow" />
</g:formRemote>
I'm stuck on the same problem, Nearly figured it out,
what you need to do, is send back the Grails webflow "_flowExecutionKey" that keeps
track of the current state,
I'm sure you've seen this, as its the only decent result Google finds.
I send an ajax request to an action, which populates a template and sends it back
with an input tag,
<input id="flowExecutionKey" name="_flowExecutionKey" value="${request.flowExecutionKey}" size="100"/>
But you could try send a temple back marked up like JSON with the "_flowExecutionKey" along with the data you want to send back,
That's my two cents
As well as keeping track of the execution (as Daxon posted), you'll need to make sure your buttons are named _eventId_next and _eventId_skip. g:submitbutton is normally clever enough to do this for you but it might not be inside of a remoteForm.
Also, my web flow code uses the parameter execution, not flowExecutionKey - which version of Grails are you using?
Here a solution that works in grails 2.5.3 at least for one single action. The id and name of the button are automatically modified to include "eventId" as prefix but this still did not work for me unless I added _event_id manually as input parameter. However, I'm not sure how this can work for multiple possible events.
<g:formRemote name="flow1Form" url="[controller:'user', action:'gettingStartedAjax']" update="wizardDiv">
<input type="hidden" id="execution" name="execution" value="${request.flowExecutionKey}"/>
<input type="hidden" id="_eventId" name="_eventId" value="next"/>
<fieldset class="form">
</fieldset>
<fieldset class="buttons">
<g:submitButton name="next" value="Next flow"/>
</fieldset>
</g:formRemote>

Resources