[cells-devel] Re: Question about Cells; defobserver for both I and O

Ken Tilton kentilton at gmail.com
Fri Jun 9 16:14:59 UTC 2006


Lars Rune Nøstdal wrote:
 > Hi Lispers,
 > Ok, starting to get the hang of this, but I'm having a small issue
 > maybe you guys could help me with.
 >
 > I'm playing with some AJAX-stuff and .. hm .. not sure how to explain
 > this proper, but ..

Fair warning: I have never programmed a Web app, barely done anything 
with HTML, and understood almost nothing of what you wrote. :) But this 
(check me: input form field initialized from a database record field, 
then overwritten by user so data must flow the other way back to the 
DB?) happens all the time in standalone apps, so...

 >
 > I have an INPUT-element (HTML) that can be used for both input of data
 > (client-initiated) and output of data (server-initiated), and I'd like
 > to block the observer so it does not react on input from the client and
 > tries to re-update the element ..
 >
 > ..or maybe "blocking" the observer isn't right at all, maybe I'm going
 > about this the wrong way..?

As I said, this comes up all the time, and what you tried is the 
tempting automatic flow:

   DB(existing value -> Input(as initial value) -> DB(new value)

Your code is what I think about writing even after ten years of using 
Cells. So how do we break the cycle? There are several ways I have 
handled this.

1. In the slot definition, specify:

        (value ...etc... :unchanged-if 'string=)

You will still make the return trip to set the input field 
unnecessarily, but that will be an NOP because the new value will be 
seen as unchanged, stopping propagation (including calling observers). 
The default test is EQL and it is easy in even simple code for 'string= 
but un-EQL strings to arise and start cycling.

To avoid even the beginnings of a roundtrip, hey, have the observer take 
a peek at where it is about to write and decide if it needs to. Not as 
much fun as letting Cells worry about it, but this one observer (I 
gather) is handling all the HTML input fields, so...?

Now I revert to my earlier disclaimer about being Web-ignorant: I think 
The Right Answer overall will be decided by the exact nature of the Web 
stuff, so I will just continue dumping alternatives

2. Does the DB flow to the form only when the form is opened? If so, the 
HTML input fields can have a something another Cells user just 
requested: a rule that runs once at initialization time and then becomes 
a /Cells/ input. ie, the slot starts as c-formula but then becomes 
c-input. (No dependencies are recorded during the initial rule 
invocation.) Only the HTML input field has an observer writing back to 
the corresponding DB field. Now if only cells had some frickin decent 
doc I could tell you the syntax. Maybe:

      (c-formula (:inputp t)
         <code to lookup value for this field>)

If that is what you settle on and it does not work I will research further.

3. if you are in a multi-user environment or for any other reason need 
to update the form programmatically at the same time the user is typing, 
well, things will be pretty exciting for the user <g>, and it may be 
time to consider the failsafe: do not try to use Cells dataflow where 
the application really needs to decide the dataflow. An application flow 
will have to be concocted, hopefully facilitated by Cells, but always 
keep in mind that the functionality might dictate more savvy than the 
Cells changed/not-changed propagation smarts.

hth, ken

 > Here is some code:
 >
 >
 > (defobserver value ((value-attribute ValueAttribute))
 >   (cells::trc "ValueAttribute changing from" old-value :to new-value)
 > (terpri)
 >   ;; Update the value-attribute of the HTML-element on the client-side.
 >   (setAttribute (parent-of value-attribute)
 >                 (name-of value-attribute)
 >                 "value"
 >                 (princ-to-string (value-of value-attribute))))
 >
 > (defmethod onkeyup ((value-attribute ValueAttribute) (parent Container)
 > &rest event-args)
 >   (format t "onkeyup: ~A~%" (fifth event-args))
 >   (setf (value-of value-attribute)
 >         (first event-args)))
 >
 >
 > `onkeyup' is called from the client-side and since (setf value-of ..)
 > triggers the observer for the slot `value', it tries to "redraw" what's
 > already on the client-side.
 >

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Beaming husband to scowling life, New Yorker cartoon



More information about the cells-devel mailing list