Creating forms help

Enonic version: Enonic XP 6.14.1
OS: Windows 10

Hi,

Following the example with countries in the documentations I’m trying to create a form to create countries on frontend. I have created the form below as a part:

<div>
    <form data-portal-component-type="part" id="form">
        <label>DisplayName</label>
        <input type="TextLine" name="displayName"></input>
        <br/>
        <label>Description</label>
        <input type="TextArea" name="description"></input>
        <br/>
        <label>Population</label>
        <input type="TextLine" name="population">
        <br/>
        <input type="submit" value="Submit" action="">
        </input>
        <br/>
    </form>
</div>

I’m not sure how to write the js behind that form and how to assign it to this form. I read projects like dictaphone and office_league but I don’t get very well how they work. I can’t find any simple example in the documentation or on the Internet. Could someone help please?

Regards.


Hi Jorge!

What you seem to be missing is a controller. The controller can be implemented through Javascript directly in the controller that renders your part (or optionally as a service).
As this doc states http://docs.enonic.com/en/stable/developer/ssjs/http-controllers.html , you should implement the follwing to accept a post request:

exports.post = function(req) {}

That should handle the form submission. If you really want to create editorial content based on user generated data you then need to use the content library to create the data. I believe you will find an example (that might not be best practice, but it is at least an example of how this can be done) in the “comment” feature of the superhero app: https://github.com/enonic/app-superhero-blog/blob/master/src/main/resources/site/services/comments/comments.js

Another important thing is to make sure your form submits data to the right endpoint, in this case your part. Simply generate the submit url using the portal API’s compontentUrl function. http://repo.enonic.com/public/com/enonic/xp/docs/6.14.3/docs-6.14.3-libdoc.zip!/module-portal.html#.componentUrl
Optionally use serviceUrl function if you are submitting to a service like the superhero example does.

NB! If you are posting to the content API, remember it will default to the repository and branch in context, as such you should explicitly specify that you want to write to the draft branch (and optionally publish the item) in order to avoid inconsistency.

Hope this moves you forward!

3 Likes

Hi Thomas,

Thanks a lot. That was very helpful.

Regards.

Jorge, just make sure that you really want to create your content using the Content API vs writing to a repo using the node API. This would be the recommended way of handling user-generated-content.

Also, check out this new library that might simplify writing to a custom repo: https://market.enonic.com/vendors/rune-forberg/appersist

1 Like

What I really want to do is to write and send files to a repo using the node API. I had all the pieces but I wasn’t sure how to connect them so I decided to play around with a more simple example like posting a simple form using the Content API.

2 Likes

Hi,

How can I tell the form that it has to use the post method in the javascript behind? As I can’t debug and the intellisence doesn’t tell much, how can I know what I have to post? I’m not sure if I’m posting everything I have to post. I checked other examples, I understand it but they use different variables and as I can’t debug or inspect what i have it makes it really hard to know if I’m doing the right thing. Could you advise please?

Regards.

Hello Jorge,
usually you say in a form what method to use or in ajax form what method to use and in controller you create export.post or export.get method to work with.

In the example @tsi has given the link to there’s a form tag with post method.

<form action="#" data-th-action="${postUrl}" data-th-attr="data-posturl=${postUrl}" method="post" id="commentform" class="comment-form">
                    <div data-th-if="${user}" data-th-remove="tag">
                        <p class="logged-in-as">
                            Logged in as <a data-th-href="${profilePage}" data-th-text="${user.displayName}"></a>.
                        </p>
                    </div>
...
2 Likes

Hi Nat,

I’m trying to call the post method on the javascript behind the html form but I’m not sure how to do it.

exports.post = function(req){ … }

Regads.

var portal = require('/lib/xp/portal'); // Import the portal library
var thymeleaf = require('/lib/xp/thymeleaf'); // Import the Thymeleaf library


// Handle the GET request
exports.get = function(req) {

    // Get the country content as a JSON object
    var content = portal.getContent();

    // Prepare the model object with the needed data from the content
    var model = {
        name: content.displayName,
        description: content.data.description,
        population: content.data.population
    };

    // Specify the view file to use
    var view = resolve('country.html');
    var postUrl = this.post;

    // Return the merged view and model in the response object
    return {
        body: thymeleaf.render(view, model)
    }
};

exports.post = function(req){
    log.info("this is a log test");
}
<div>
    <form action="#" data-th-action="${postUrl}" data-th-attr="data-posturl=${postUrl}" method="post" id="countryId">
        <label>DisplayName</label>
        <input type="TextLine" name="displayName" data-th-text="${name}"/>
        <br/>
        <label>Description</label>
        <input type="TextArea" name="description" data-th-text="${description}"/>
        <br/>
        <label>Population</label>
        <input type="TextLine" name="population" data-th-text="${population}"/>
        <br/>
        <input type="submit" value="Submit"/>
        <br/>
    </form>
</div>

I tried the code before but it doesn’t work

Multiple issues here, but try creating the postUrl inside the model object, and instanciate it with the portal function componentUrl() rather than this.post…

1 Like

Ive been following the same approach than in hero app. (but as you said it’s not a good a practice). I’ve read the whole documentation and I haven’t found any information or example that helps with posting a simple form.

I’ll receive an Enonic training soon so I guess things will be much more clear afterwards.

How can I do that? I found only this information about componentUrl

http://xp.readthedocs.io/en/stable/reference/view-functions/componentUrl.html

How can I instantiate postUrl in the model (XML file ?)

Hi Jorge,

An answer here would perhaps be a bit too long. There’s quite a few details I need to explain to make a form post work. But let’s try to keep it simple.

Enonic XP relies on you using the exports. keyword inside your controllers. A controller is basically any JavaScript-file. This export-thing lets you listen to different types of requests (like GET, POST, etc). The most common one is in XP .get. Meaning you’d do something like this: exports.get = function(req) { /* loads of code */ }. That code in there will run when that particular request hits the controller. In one controller you can export multiple types! So, one get for rendering the form (setting the form action URL using portal.componentUrl) and one post for receiving the post.

With exports.post all the form data is inside the req object sent as a parameter into the function. Inside it, you’ll find .param with all fields. Use log.info to dump the entire req-object and look at it. The docs have a handy overview of it too - http://docs.enonic.com/en/stable/developer/ssjs/http-request.html.

Check out Corporate Theme source code, it has a form post+get handling done this way. Two html-files with Thymeleaf, one for get (show the form) and one for post (show a thank you). All the logic is in the JavaScript-file. https://github.com/enonic/app-corporate-theme/blob/master/src/main/resources/site/parts/contact/contact.js

Hope that helps!

2 Likes

Hi Bobby,

Thanks a lot for your answer. I could make my form work after your explanation and corporate example :smiley: . Now everything is much more clear.

Kind regards.

1 Like

I should mention that this really is just some frontend-code. Besides URL used to submit, it doesn’t have any ties to Enonic as such, and it could have been written differently. Also, the code is a bit old-fashioned.

Xp-forms is under development, and will handle all of this a lot more fluently, while also being less coupled with Enonic XP. (It will be a React-app both in admin and frontend) Not sure when it will be done, but I will resume work on it next week.

1 Like

Hi Jorge,
great you’ve managed your form to work. Corporate and blog examples are a huge help to understand and use enonic :slight_smile:

2 Likes

True. It’s a bit hard to start with but once you get the basics it’s straight forward.

2 Likes