2

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.
            ]
! !
Kwaku
  • 276
  • 2
  • 15
  • Stephen-Eggermont's and MKroenert's answers are both useful. I have put in a new version of the question which is less implementation oriented. – Kwaku Jan 16 '15 at 10:52
  • the second code example in my answer shows you how to get the values of the input fields. The only thing left to do is to put them in a dictionary instance with `at:put:`. – MKroehnert Jan 16 '15 at 10:55
  • updated JQuery example to also put the values into a dictionary. – MKroehnert Jan 16 '15 at 11:05
  • another update to my answer to contain a complete example. @Kwaku. – MKroehnert Jan 16 '15 at 17:07
  • @MKroehnert, thank you! I tested it and the code of the complete example worked fine. I have added it to the question in `fileIn` format. – Kwaku Jan 26 '15 at 09:38

2 Answers2

4

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
Community
  • 1
  • 1
MKroehnert
  • 3,637
  • 2
  • 34
  • 43
1

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: aCanvasand 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]
Stephan Eggermont
  • 15,847
  • 1
  • 38
  • 65
  • With 'duplication' you mean the field label and the field name? How is this done differently in Amber Smalltalk? – Kwaku Jan 04 '15 at 04:10
  • Maybe the form could have a different layout, but it seems to me that the amount of input fields and text can not be reduced. It is also not stated if the form is given or generated in some way. – MKroehnert Jan 15 '15 at 18:53
  • @MKroehnert you might want to take a look at seaside too – Stephan Eggermont Jan 16 '15 at 08:12
  • @StephanEggermont I do know some basic things about Seaside. But the question was about iterating through the fields with Amber. – MKroehnert Jan 16 '15 at 08:40
  • 1
    @StephanEggermont the first part of the answer is very fine. The method which creates the form is very readable. How does the #renderField:on: method look like and how do I get the field values? – Kwaku Jan 16 '15 at 10:57