I have a Yesod form for editing the contents of some static pages which are written using markdown (processed using Pandoc). I want to have two buttons - a 'preview' button which processes the markup and displays the result underneath the form, and a 'submit' button which saves the contents to the database.
What is the simplest way to do this with Yesod? All the form examples in the Yesod book have exactly one button. I've looked at the exposed functions / api, but I even if I add more than one submit button with different names and/or values to the form I can't figure out how to get Yesod to tell me which one was pressed.
Can anyone give me a simple example of a form with more than one button in Yesod, which trigger different actions?
You can just use the Input form functions to get the raw values, and explicitly set a name attribute on the various buttons. Something like this in the HTML:
<input type="submit" name="preview" value="Preview">
And in the Haskell code:
res <- runFormPost ...
isPreview <- runInputPost $ iopt boolField "preview"
if isPreview then ... else ...
Sorry if this doesn't typecheck, I don't have my normal development system right now. But I think this is the right general approach.
Related
I have a complex Bean object that I want to update. Because it is too much complex, it can't be edited in the DataTable (inplace editing). Let's say that my page have this structure:
-> Input Form
-> DataTable for Listing
So I save the object using the Input Form and it appears inside the DataTable. This part is easy. Now, I need to edit the object inside the DataTable. Since the object is too much complex, it is not viable to edit in-place. So I must pick the row data and put it in a form to be able to sumbit it.
My problem is, I haven't come to a way of editing the data that I would like.
I've done it in multiple ways.
I've created a page only for the edit. I call the page passing the object's ID in the URL.
I copied the Input Form inside a Dialog. While this is great for editing, using a dialog had led me into problems (complex validations patterns, dialogs inside dialogs, etc).
I put the row data back into the Input Form and use Primefaces-Extensions spotlight component to ensure that the user will only work within the form. I've added a button to cancel edition also.
I didn't like any of them, although the third is the best of them, to me. But I'm also out of ideas of how to design data editing. Do you guys have some edit designs that you would like to share?
Thanks in advance.
I have a form created with jade, it does not postback when submit button is clicked.
I have looked at many similar problems, I tried the solutions, which include ensuring that the input fields all have a 'name', I have made sure all the input field have a name but the form still does not post back, here it is
//views/users/new.jade
h1 New User
form(action="/users", method="POST")
p
label(for="username") Username
input#username(name="username")
p
label(for="name") Name
input#name(name="name")
p
label(for="bio") Bio
textarea#bio(name="bio")
p
input(type="submit",value="Create")
The post handler is this
//routes/users
module.exports=function(app){
app.post('/users',function(req,res){
if(users[req.body.username]){ //Check if user exists
res.send('Confllict, 409')
}else
{
//add to users list
users[req.body.username]=req.body;
res.redirect('/users');
}
});
};
Jade uses indention to show what content goes between the tags
p
this is inside the p tags
also there is shorthand
p this is also in the tag
in your original code you are telling Jade that there is a p tag then the next line is outside the p tags.
This is an easy problem to run into if you aren't careful with indentation using Pug (previously Jade). I realize this is an old question, and it has several hits so perhaps this answer will shed some light for new Pug users.
The problem with the OP's code is the Form does not know how to post without a button, and the Submit button doesn't know where to post to without being associated with the Form. Why? Indentation.
Jade and Pug tips for success:
They produce html, so it helps to think in html layouts when developing the template (would you put text outside of your p element? Of course not).
Pug uses indentation to form layout and element hierarchy.
Html Forms must enclose the elements that are to be associated or bound to it.
A Submit Button does nothing unless you define an event handler.
Forms define a destination in their definition, which a button type element can leverage.
In the code listed by the OP, every Pug element is left-aligned. This puts all elements at the same level, so there is no hierarchy or nesting. Since there is no other event handler explicitly defined for the Submit button, nothing happens when it is clicked, despite the form having an action and a valid method.
To fix this, the Input (submit button) can be nested inside the Form.
Reworking the code to include indented hierarchy will enable the POST to function as expected (removed all the other elements for readability):
h1 New User
form(action="/users", method="POST")
label(for="username") Username
input#username(name="username")
label(for="name") Name
input#name(name="name")
label(for="bio") Bio
textarea#bio(name="bio")
input(type="submit",value="Create")
The resulting form won't be a pretty, but it will function:
The Form has an action and method.
All dependent elements are indented.
The input has a type of Submit and is child to the form.
Of course, a server must have a binding at the address to receive the data in order to do anything with it.
I am working on a large, worldwide application, which includes access from areas of low bandwidth. As such, I want to use a minimum of SSJS or partial refreshes for all the complex hide/when calculations. Here is what I have so far for a simple "hide/when":
A Yes/No radio button, with CSJS to show a panel ("Yes") or hide the
panel ("No").
The panel has a formTable inside it, and the values are shown or hidden, as per #1.
In the XPage's onClientLoad, the following code is run:
// "getRadioValue" is a simple script to return the value of a radio button
var v_value = getRadioValue("#{id:radioButton}");
v_div = '#{javascript:getClientId("radioButtonPanel")}';
// show or hide div simply use dojo to change the display of the panel
if (v_value == 'Yes') {
showDiv(v_div);
} else {
hideDiv(v_div);
};
For a new document, the onClientLoad script will hide the "radioButtonPanel" successfully. Changing the radio button to "Yes" will show the radioButtonPanel, just as clicking "No" will hide it. It works great! :-)
Once the document is saved and reopened in read mode, though, the onClientLoad CSJS event should read the saved value in the document, and decide to show the panel or not. When the document is opened in edit mode, the onClientLoad fires, reads the radioButton value and successfully shows or hides the panel.
This is what I've tried so far, to get it to work in read mode:
In CSJS, using "#{javascript:currentDocument.getItemValueString('radioButton'}" to get the value,
Doing some calculations in the "rendered" or "visible" properties, but that's SSJS and, if hidden, prevents any of the "show/hideDiv" CSJS visibility style changes.
Adding an old fashioned "div" to compute the style (which is what I used to do before XPages), but since I can't do pass-thru html any more, I can't seem to get a CSJS calculation for the style. Ideally, I can do something like this:
<div id="radioButtonPanel" style="<ComputedValue>">
Where the ComputedValue would read the back end value of the document, and decide to add nothing or "display:none".
Note that I don't want to use viewScopes, since this long form would need many of them for all the other hide/when's.
Is there any way to make this 100% CSJS? I feel like I'm very close, but I wonder if there's something I'm just missing in this whole process.
First, rather than computing style, I'd recommend computing the CSS class instead -- just define a class called hidden that applies the display:none; rule. Then toggling visibility becomes as simple as a call to dojo.addClass or dojo.removeClass.
Second, I see that you're using the #{id:component} syntax to get the client ID of the radio button but using SSJS to get the client ID of the panel. Use the id: syntax for both; this is still just a server-side optimization, but if there are many instances of these calculations, it adds up. Similarly, replace #{javascript:currentDocument.getItemValueString('radioButton'} with #{currentDocument.radioButton}. Both will return the same value, but the latter will be faster.
Finally, any attribute of a pass-thru tag (any component with no namespace, like xp: or xc:) can still be computed, but you'll need to populate the expression by hand, since the editor doesn't know which attributes for valid for these tags, and therefore doesn't provide a graphical expression editor. So if the ideal way to evaluate the initial display is by wrapping the content in a div, the result might look something like this:
<div class="#{javascript:return (currentDocument.getValue('radioButton') == 'Yes' ? 'visible' : 'hidden');}">
<xp:panel>
...
</xp:panel>
</div>
I'm interesting in creating a widget in Yesod with the following properties:
By default, it renders simply as some text "Title"
When moused-over, a small link "Edit this" appears on the upper-right corner
If the user clicks on the link or mouses over it, the text is replaced with a text field/area with the text in it, for editing
When the user presses ENTER, a REST request is made to the server to update the value; when the update is confirmed the form disappears and updated text is now present in the document
To a large degree, this is a strictly JS job which is mostly out of scope for Yesod. However, there is one important point: we'd like the form itself should be generated by Yesod using yesod-forms, and not wired up manually. But the situation here is a bit strange: normally forms are static, but here the form needs to be different depending on what the data is, and Yesod might need to ship a new form to the user after the REST update. Can Yesod do this? Additionally, what is the story, as far as validation is concerned?
I have a simple ContactEditPanel which contains a form and a number of textfields. Up until now I included an AjaxSubmitLink in this panel which, if the form content is valid, saves/updates the Contact instance contained in the Panel model. So far so simple. However now I'd like to remove the link in order that I may, depending on the context in which I use the ContactEditPanel, place the submit link at different levels of my overall component hierarchy. For instance in one context I'd like to use to flip between ContactEditPanel and ContactViewPanel with a bar of actions above the current view (edit | save , cancel). Another context would be to use ContactEditPanel in a standalone way (maybe part of a multi-step process) with just a save link below.
I was contemplating refactoring my ContactEditPanel to extends FormComponentPanel rather than Panel as described here but I'm not sure whether this is the right approach and I'm having trouble wrapping my head around this.
Any help would be most appreciated!
Many Thanks,
A
Your using the panel like a FormComponent so extend FormComponentPanel, it will allow you to keep all the validation you write contained to the component and also allow you to reuse it as you wish.
Just think of it as you've created a new FormComponent, like a TextField or DropDownChoice.