Reputation: 276
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>
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.
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.
]
! !
Upvotes: 2
Views: 405
Reputation: 3737
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
Upvotes: 4
Reputation: 15907
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]
Upvotes: 1