Why is the callback not being executed? - smalltalk

I'm writing a basic web application (begin with seaside) but the callback never runs...any ideas?
renderContentOn: html
| group |
html form: [
html text: 'Gender: '.
group := html radioGroup.
group radioButton
selected: self contact isMale;
callback: [ self contact beMale ].
html text: 'Male'.
group radioButton
selected: self contact isFemale;
callback: [ self contact beFemale ].
html text: 'Female'.
html break.
html anchor
callback: [ mmpiItems setAnswer: (self option) ];
with: 'Next'.
]

An anchor inside the form does not submit the form, only a submitbutton does. This is not defined by Seaside but by HTML.
You can find more information in the seaside book on writing forms with Seaside: http://book.seaside.st/book/fundamentals/forms

You must use submitButton instead of an anchor or any other button.
Your code would look like this:
renderContentOn: html
| group |
html form: [
html text: 'Gender: '.
group := html radioGroup.
group radioButton
selected: self contact isMale;
callback: [ self contact beMale ].
html text: 'Male'.
group radioButton
selected: self contact isFemale;
callback: [ self contact beFemale ].
html text: 'Female'.
html break.
"Use a submitButton instead of a regular anchor/button"
html submitButton
callback: [ mmpiItems setAnswer: (self option) ];
with: 'Next'.
]

Related

Cant seem to fully understand how textInput works on a super simple website

So basically all I need to do is add a 'User' object to a OrderedCollection.
All I need to grab from the user is the username and password.
Once the submit button is clicked, I would need to add the User to the collection and return to home page (which I guess would be done by calling #answer).
Read like 99x times the seaside book on textInput but I fail to understand where is the data stored once the form is submitted.
Any intel is highly appreciated.
This is my current form:
html form: [
html text: 'Username: '.
html textInput
callback: [ ];
value: 'Enter username here'.
html break.
html text: 'Password: '.
html textInput
callback: [ ];
value: 'Enter password here'.
html break.
html submitButton
callback: [ ];
value: 'Add user']
If you read the book 99x times, then you did not read the code samples of forms. Your example is even given directly in the example of ContactView in http://book.seaside.st/book/fundamentals/forms/textinputfields
In your code, the callbacks of the text input fields are empty (i.e. no code). On form submission, Seaside invokes these callbacks with the values entered in the text fields. Finally, it will invoke the submit button callback.
Your code could be:
| user pass |
html form: [
html text: 'Username: '.
html textInput
callback: [:userValue | user := userValue ];
value: 'Enter username here'.
html break.
html text: 'Password: '.
html textInput
callback: [:passValue | pass := passValue ];
value: 'Enter password here'.
html break.
html submitButton
callback: [ self addUser: user withPassword: pass ];
value: 'Add user']

Smalltalk seaside #call: rendering a blank page

So I have a seaside application. The first component just render a subcomponent:
MCRootComponent>>initialize
super initialize.
self main: MCMainComponent new.
MCRootComponent>>renderComponentOn:html
renderContentOn: html
html render: main
Now the subcomponent being rendered looks like:
MCMainComponent>>renderContentOn: html
html tbsForm:[
html tbsContainerFluid: [
html anchor
callback: [ self call: (MCServiceOrderComponent from: MCServiceOrder new)];
with: 'New Service Order' ]]
and the MCServiceOrderComponent:
MCServiceOrderComponent>>initialize
super initialize.
customerComponent := MCClienteComponent new.
vehicleComponent := MCVehicleComponent new.
vehicleComponent lookupCallback: [
self show:(MCVehicleLookupComponent new) onAnswer:[:vehicle|
vehicle ifNotNil: [
serviceOrder vehicle: vehicle.
vehicleComponent objectToRender: vehicle.
customerComponent objectToRender: vehicle customer ]]]
MCServiceOrderComponent>>renderContentOn: html
html heading level1 with: 'ServiceOrder'.
html tbsForm with: [
html render: vehicleComponent.
html render: customerComponent.
]
So far this renders allright. Notice the lookup callback being passed to the MCVehicleComponent. This block is passed to the callback on a button rendered inside the MCVehicleComponent.
MCVehicleComponent>>renderContentOn: html
self renderContainer: 'Vehicle' on: html with: [
self renderSearchFor: #id on: html with: self lookupCallback.
self renderInputFor: #maker on: html.
self renderInputFor: #model on: html.
self renderInputFor: #color on: html ]
MCVehicleComponent>>renderSearchFor: aSymbol on: html with: aBlock
html tbsFormGroup: [
html label: aSymbol asCapitalizedPhrase.
html tbsInputGroup: [
html textInput tbsFormControl on: aSymbol of: self objectToRender.
html tbsInputGroupButton: [
html tbsButton callback: aBlock;
with: [ html tbsGlyphIcon iconSearch ] ] ]]
It should #call: to a MCVehicleLookupComponent and return the result back. However the reality is that as soon as the #call: it's made, the page content goes blank. I have tried calling the MCVehicleLookupComponent directly from the MCMainComponent and it works fine, so I know the problem isn't there. Do you have any idea what could be causing this behavior?
I'm fairly new at smalltalk so please be patient with the stupid questions and horrible code (this is my first application. Any suggestions are welcome).
Turns out I was calling out the wrong component. Everything works as a charm. Sorry.

how to create multiple bootstrap tooltips for dynamically generated elements

I have 2 selector and their own titles. My elements are generating dynamically by jquery.I wrote this code:
$("body").tooltip({
selector: '.Edit',
title: 'edit',
placement: 'bottom'
});
$("body").tooltip({
selector: '.Delete',
title: 'delete',
placement:'bottom'
});
Each of them works correctly alone,but it doesn't work together.
And I have to write title in js(not in data-original-title attribute in my HTML tag)
Instead of invoking multiple tooltips, modify the placement variable to read it from the html element.
placement : $(this).data("placement") || 'top',

Seaside - Reporting with submit buttons

Is something like the following valid?
TransactionReport := WATableReport new
rows: SpendingManager instance entriesForPosting asArray;
columns: (OrderedCollection new
add: (WAReportColumn
renderBlock: [ :each :html | (html submitButton
callback: [ SpendingManager removeTransaction: each. self renderReport ];
text: 'Backout Transaction')]
title: '');
It does actually render the submit button with each row, but clicking it doesn't appear to do anything.
I've been able to kinda of accomplish this, though it's not as pretty as a button:
add: (WAReportColumn new
title: '';
valueBlock: [:anEvent | 'delete'];
clickBlock: [ :each | SpendingManager instance removeTransaction: each]);
yourself);
Would still love some feedback.
Submit Buttons that do nothing are most likely not inside a form tag. So can you check if your report works if you embed it into a html form: [] block?
If a form is not an option, you can replace the submit buttons with anchors. You can use css to make anchors look like buttons if that aspect is important.

Smalltalk new lines?

I can't get this to work at all:
renderContentOn: html
html form: [
html textInput
on: #newEmp of: self.
html submitButton
callback: [ self addEmployee: newEmp ];
text: 'Add Employee'.
self employeeNames do: [ :eachEmp | html text: Character cr asString. html text: eachEmp.]
]
I just keep getting my output on one line. Am I missing something? I've tried several variations of cr but none have worked thus far.
Don't rely on carriage returns to display your data in the browser. The employee names obviously belong either in a list or a table (you are providing a list of names):
html unorderedList: [
self employeeNames do: [ :eachEmp |
html listItem: [
html text: eachEmp ] ] ]
You most certainly want html break instead of html text: Character cr or any variation thereof. HTML intentionally treats newlines in text as simple spaces.
Other than that, the idea of max-leske to use item lists is much to be preferred.