Hello,
At present magritte is a little limited when you have two form fields
which are related in some way. I have come up with a scheme which works,
suggestions are of course very welcome.
Here is an example from the top....
description0020ServiceType
^ MASingleOptionDescription new
accessor: ((#serviceType asAccessor) update:
#serviceTypeChangedTo:);
reference: MAClassDescription new;
options: [ DTIServiceTypes allSubclasses ] asDynamicObject;
default: DTIDeliveryWholesale;
componentClass: MASelectListComponentSU ;
beRequired;
bePersisted;
yourself
Service type is select list which changes the values in other fields in
the form, when the users switches it.
1. The first innovation is the setting of the priority in the method
selector name. I have used this for 3 days and it works really well.
(Enhancement available in Magritte-CustomBuilder package)
2. The second innovation is ((#serviceType asAccessor) update:
#serviceTypeChangedTo:) This is shorthand for...
(MASelectorAccessor read: #serviceType write: #serviceType:)
propertyAt: #update put: (MASelectorAccessor write:
#serviceTypeChangedFix:)
So we have normal access to the datamodel via the reading and writing
accessors, this is the sort of accessing that persisting (and mementos)
would use, but GUI elements can use additional optional update accessor.
#serviceTypeChangedTo: will modify other fields in the model. (Well
actually the model's memento but we will come to that).
Where GUI elements used to write to objects using the standard
Object-#write:using: there is now an #Object-#update:using: which uses
the update accessor if present.
3. RealMementos
The problem with the way that the Gui does mementos now is that it
operates on a dictionary of the models data. The mementos have no
awareness of the model itself. Enter MARealMemento... This uses a
dictionary checks as before BUT importantly read/writes from the GUI are
performed upon a real copy of the model, which is returned upon commit/save.
It also has methods (not yet used) #snapshot, and
#hasChangedSinceSnapshot, which the gui can us in order to only up date
items which have changed since the previous update.
This means that the update methods can modify the values in other fields
and the GUI will see these changes if it is re-rendered using Scriptaculous.
Two caveats are that items being edited by an InternalEditor will will
need to a) have an MAStraitMemento so that they operate directly on the
same model (since they are in the same UI) and (b) the internally edited
objects must be modified not replaced (since the InternalEditor
currently has and is likely to keep a reference to the object itself)
4. MASelectListComponentSU
The scriptaculous addition to the standard select list component, calls
the #update: accessor when the users changes the selection, and it
renders updateContentOn: of the containing MAContainerComponent. So the
display of all fields is refreshed.
I have one other refinement... (not yet implemented in this form)
5. Modifying readonly isVisible
accessor: ((#check asAccessor) readonly: #isCheckDisabled);
accessor: ((#check asAccessor) visible: #isCheckVisible);
The code so far is available in Magritte-RealMemento ,
Magritte-Scriptaculous, Magritte-CustomBuilder
I think that this potentially moves magritte up a level in
user-interactivity
enjoy
Keith