简体   繁体   中英

How do I get the values of all the fields of a form?

I have a HTML form like this in a client side Amber solution

<form id="myForm1">
  Creator:  <input type="text" name="creator" />
  <br>
  Title:  <input type="text" name="title" />
  <br>
  Description:  <input type="text" name="description" />
  <br>
  Doctype:  <input type="text" name="doctype" />
  <br>
  Tags:  <input type="text" name="tags" />
</form>

Question

How do I iterate through all of the fields of the form in order to put the content of the fields into a Amber dictionary with the field name as key and the text content as value?

New version of the question after answer by Stephen-Eggermont and MKroenert

How do I get the values of all the fields of the form in order to put them into an Amber dictionary with the field name as key and the text content as value?

Or is there an idiomatic way to create a form and retrieve the values?

Note : The form may be constructed with Amber code if this makes things more readable.

References

Edit after answer: FileIn code

The answer provided by MKroenert works fine

Below is his code I tested. It may be filed in directly in a workspace

    Widget subclass: #AmberFormExample
    instanceVariableNames: 'dictionary inputs'
    package: 'TodoList'!

!AmberFormExample methodsFor: 'not yet classified'!

collectValues
    inputs do: [ :each |
        dictionary at: (each asJQuery attr: 'name')
            put: (each asJQuery val).
        ].

Transcript show: dictionary printString
!

initialize
    dictionary := Dictionary new.
    inputs := Array new.
!

renderInput: inputName on: html
    html p: [
        html label with: inputName.
            inputs add: (html input id: inputName;
                name: inputName;
                yourself)]
!

renderOn: html
    inputs removeAll.
    html form id: 'myForm1'; with: [
        #('Creator' 'Title' 'Description' 'Doctype' 'Tags') do: [ :each |
            self renderInput: each on: html]].
    html button
        with: 'Collect Inputfield Values';
        onClick: [
            self collectValues.
            ]
! !

I reused the code from this SO question and rewrote it in Amber to address the first part of your question. Here is how you iterate over all input fields:

(('#myForm1 *' asJQuery)
    filter: ':input')
        each: [ :thisArg :index |
            console log: thisArg ] currySelf

This Amber recipe is required to get access to the JavaScript this .

Printing both name and value of the input fields to the JavaScript console can be done like this:

(('#myForm1 *' asJQuery)
    filter: ':input')
        each: [ :thisArg :index |
            console log: (thisArg asJQuery attr: 'name').
            console log: (thisArg asJQuery val)] currySelf

Putting the values into a dictionary:

| dict |
dict := Dictionary new.
(('#myForm1 *' asJQuery)
    filter: ':input')
        each: [ :thisArg :index |
            dict at: (thisArg asJQuery attr: 'name')
                put: (thisArg asJQuery val)] currySelf

As for the second part of your question, there is the Web package in Amber which contains Classes for generating HTML pages. What you do is to create a subclass of Widget and implement the renderOn: html method. The object passed in as html parameter is of type HTMLCanvas and can be used to create an HTML form like this:

renderOn: html
    html form with: [
        html input id: 'creator'.
        html input id: 'title'.]

Here is a complete example. Take it as a starting point and be aware that it may not be the most efficient way of doing things

Widget subclass: #AmberFormExample
    instanceVariableNames: 'dictionary inputs'
    package: 'Examples'

AmberFormExample>>initialize
    dictionary := Dictionary new.
    inputs := Array new.

AmberFormExample>>renderOn: html
    inputs removeAll.
    html form id: 'myForm1'; with: [
        #('Creator' 'Title' 'Description' 'Doctype' 'Tags') do: [ :each |
            self renderInput: each on: html]].
    html button
        with: 'Collect Inputfield Values';
        onClick: [
            self collectValues.
            ]

AmberFormExample>>renderInput: inputName on: html
    html p: [
        html label with: inputName.
            inputs add: (html input id: inputName;
                name: inputName;
                yourself)]

AmberFormExample>>collectValues
    inputs do: [ :each |
        dictionary at: (each asJQuery attr: 'name')
            put: (each asJQuery val).
        ].

After implementing this class in a running Amber instance the following code can be used to execute it:

AmberFormExample new appendToJQuery: 'body' asJQuery

There is a lot of duplication in your form. You might want to take a look at HTMLCanvas and how it is used in IDE.

You could add a method renderField: aFieldName on: aCanvas and reuse that 5 times. Did you take a look at Seaside?

The end result should be something like

renderOn: html
    html form with: [
        #('Creator' 'Title' 'Description' 'Doctype' 'Tags') do: [:each |
            self renderField: each on: html]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM