[cells-devel] another redundant update
Ken Tilton
kennytilton at optonline.net
Mon Apr 7 21:30:26 UTC 2008
Ken Tilton wrote:
> Andy Chambers wrote:
>
>> Hi,
>>
>> This was mentioned a while ago and is causing a problem now. When an
>> ajax request comes in, one of the things that gets updated is the
>> input value. For example...
>>
>> old: <input name="term" value=""/>
>>
>> ...user types in "progv" and hits TAB
>>
>> new: <input name="term" value="progv"/>
>>
>> We want the model on the server to update itself to reflect this
>> change but we don't need to send it down to the browser because the
>> browser already knows. The problem this is causing (and this is
>> something we'll need to take a mental note of for the future) is that
>> the event binding for the input element is lost when that element is
>> replaced. That means any actions after the first don't trigger an
>> ajax request.
>>
>> We could rebind the event on the new element but I think its better
>> not to send it in the first place.
>>
>> I think this would apply to all UI elements so if that's the case, the
>> solution is probably to filter updates containing these elements the
>> same way that ascendant and redundant nodes get filtered in the code
>> below.
>>
>> (let ((updt (loop for (h . xh) in (updates self)
>> unless (loop for (h2 . nil) in (updates self)
>> thereis (unless (eq h h2)
>> (when (fm-ascendant-p h2 h)
>> (trc nil "suppressing
>> redundant" h :seeing-ascendant h2 (id h2))
>> t)))
>> collect xh)))
>>
>> I've pushed a new version out to the repo but haven't dealt with this
>> problem yet.
>
>
> Lessee. The update happens in the observer on the xhtml slot, which is
> passed the clos instance for the node along with the old and new values,
> inter alia.
>
> (defobserver xhtml ((self html))
> (when new-value
> (trc nil "new xhtml for" self)
> (assert (u^ web-app))
> (push (cons self (format nil "$(\"#~a\").html(\"~a\")" (^id)
> (js-escape new-value)))
> (updates (u^ web-app)))))
>
> I suggest you have an option or options on the clos node that controls
> whether the update gets sent:
>
> (mk-input (:name "s" :id "s"
> :-type "text"
> :send :once ;; default t (other constraints possible,
> ;; including a closure over other variables
> ;; that returns t to send, nil not
> :any-more-info 'needed-t-control
> :value (c? (term (u^ web-apropos)))))
>
> And then:
>
> (defobserver xhtml ((self html))
> (when (and new-value (do-send self new-value old-vale))
> (trc nil "new xhtml for" self)
> (assert (u^ web-app))
> (push (cons self (format nil "$(\"#~a\").html(\"~a\")" (^id)
> (js-escape new-value)))
> (updates (u^ web-app)))))
>
> And:
>
> (defmethod do-send (self new-value old-value)
> (bwhen (s (send self))
> (case s
> ((t) t) ; parens needed, long story
> (:once (not old-value))
> (otherwise ; better be a function :)
> (funcall s self new-value old-value)))))
>
> Note I made it a method so one could just do:
>
> (defmethod ((self input) new old)
> (not old))
>
> That might be too extreme -- perhaps we /do/ sometimes need to get an
> input field out there again, perhaps with a different binding, or even
> to do symbol-completion (weird in apropos, but just as an example) --
> but the flexibility might help someday. Maybe start with a defun and see
> if a GF is ever needed.
Hmmm, I just realized you are making a library that should be long on
ease of use. Perhaps you /do/ want to have the user specifying a minimum
as the default, in which case you might well want to special do-send
on the input field, also have a 'send' parameter default to :once for
input, t for most other things, and then have it all Just Work with
fancy black belt behavior available by actually coding values for the
:send option including closures, or subclassing input if they have lots
of inputs that will have the same odd behavior.
kt
More information about the cells-devel
mailing list