Seaside - Reporting with submit buttons - smalltalk

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.

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.

Why is the callback not being executed?

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'.
]

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.

Displaying a text on a view

The code below is part of my controller function;
success: function (response) {
var text = response.responseText;
var result = Ext.decode(response.responseText);
var indexPanel = Ext.create('app.view.PersonDetails');
Ext.getCmp('mainView').push({
xtype:'person',
data: result
});
}
The code below, is the view, which i am passing values from my Controller function (above).
The code below, demonstrates hard coded data in that view (Hard coded text), but what i want to do is to display the data: result that i am passing from Controller function (above) to be displayed in the following view. How can i do this ?
Ext.define('app.view.UserInformation',{
extend:'Ext.Panel',
xtype:'person',
config: {
title:'Person details',
html:['Hard coded text'].join("")
}
});
UPDATE
The result contains several values like;
result.name, result.age. result.gender
I will be passing result to the other view.
1.) from the View, how can i add a button ? and wen the user clicks on that button how can i fetch the result.age field and do a if condition to check if the age is below 10 ?
2.) Imagine, if there's a field called, result.imageurl, how could i display the image on the other view (in a frame) ?
UPDATE2
Ext.getCmp('mainpanel').push({
title: 'Hello ' ,
xtype:'person'
});
Ext.getCmp('idOfTheView').setRecord(result.first_name);
Your question is Sencha Touch alone, not relevant to PhoneGap. :)
Suppose that your view has an id: view_id
Then in your controller function:
Ext.getCmp('view_id').setHtml(what you want to put into your view)
Updated answer:
Your question consists of several sub-questions. I'm afraid that the scope you're asking is too wide but I will answer the most important part.
(from my own application):
Ext.define('rs.view.ProductInfo', {
extend: 'Ext.Container',
xtype: 'ProductInfo',
id: 'product-info',
cls: 'product-info',
config: {
items: [
{
xtype: 'panel',
styleHtmlContent: true,
id: 'product-info-header',
tpl: [
'<div class="product-info-header">',
'<img src={image} width="100px" height="100px"/>',
'<h3>{name}</h3>',
'<h4>Price: {price}</h4>',
'<h4>Seller: {sellerUsername}</h4>',
'</div>',
],
},
],
}
});
Note that I defined a Model with attributes, {image},{name},{price},{sellerUsername}, then in the code snippet above, you can see that I use them in tpl config as if normal use in Ext.List (with store config). So how can I do it?
First, you have to define a model describing your result. obviously.
Second, define tpl in your view, I believe you can figure it out from the example above.
Finally, use this (assume that you've written the result received from server into your Model instance which I've mentioned in first step):
Ext.getCmp('your_view_id').setRecord(your_model_instance)
100% work warranty because I've used this many times. Hope it helps. Should you have any question, please leave a comment.