Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pedestal : what data flow can you use to render a newly initialized empty list?

I'm trying to make a very basic pedestal app to display a list of items, or a text message if the list is empty.

I thought what I wanted was :

  • a data model where [:root :items] would be my list of items
  • a template function for the page ([:root])
  • a static template function for the empty list
  • a dynamic template function for a list with elements
  • at the start of the application, send a message that will initialize the list to be empty
  • in rendering, respond to :
    • [node-create [] :map] by doing ... nothing ?
    • [node-create [:root] :map] by rendering the template for the full page
    • [node-create [:root :items] :map] by adding the template for the empty list

To be clear, what I want to display in the end would be (without elements)

<html>
 <div>My list</div>
 <p>There is nothing in the list</p>
</html>

and when there is something in the list :

<html>
 <div>My list</div>
 <ul>
   <li>item1</li>
   <li>item2</li>
 </ul>
</html>

Am I on the right track here ?

I'm stuck at initializing the data model to be what I want. The closest I got is this :

;; behavior.clj
(defn init-root-transform [old-value message]
  {})

(defn init-items-transform [old-value message]
  [])

(def example-app
  {:version 2
   ;; :transform [[:set-value [:greeting] set-value-transform]]})
   :transform [[:bootstrap [:root] init-app-transform]
               [:bootstrap-systems [:root :items] init-items-transform]
               ]})

;; start.cljs
... skipped...
    (app/begin app)
    (p/put-message (:input app) {msg/type :bootstrap msg/topic [:root]})
    (p/put-message (:input app) {msg/type :bootstrap-systems msg/topic [:root :items]})

The problem is that, this way, I get a data model with a single :root node containing the value {:items [] }.

It might sounds like a very silly question, but are those two data models the same ?

[:root :systems] => []
[:root] => {:systems []}

And when I boot my application, the generated rendering deltas are :

[node-create [] :map]
[node-create [:root] :map]
[value [:root] nil {:items [] }]

I don't think this is suitable for rendering my list of items, is it ?

UPDATE :

@solussd implied that the two datamodels are the same ; however, when the following delta is generated :

[value [:root] nil {:items []}]

I still can't handle it. If I add a rendering config like this :

[value [:root :items] render-items-list]

Then the render-items-list function is not called.

If I add a rendering config like this :

[value [:root] render-root]

Then the render-root function will be called, but obviously, not with the proper 'path', and I suppose it would also be called when any other change to the ':root' element in the data model is changed.

Any idea how I can fix that is welcome...

like image 344
phtrivier Avatar asked Jan 31 '14 11:01

phtrivier


2 Answers

Yes, those two datamodels are the same.

The node-create and value deltas are sufficient to send the sequence of items to your renderer, but you're rendering granularity is the whole list of items.

Your render config might look like this:

(defn render-config 
    []
    [:node-create [:root :items] render-item-list]
    [:value [:root :items] update-item-list])

If you wanted to use a template for each item in the list, e.g.,

<ul template="list-item" fields="id:id,content:item"/>

in the html template file), you might want to output deltas at the individual list item level and probably have them be keyvals in a map, e.g. a model like:

{:root {:items {:1 <item> :2 <item> ...}}}.

Hope this helps.

like image 175
solussd Avatar answered Nov 15 '22 06:11

solussd


I don't have a computer to check this right now, but I think if you add an emit pair to your dataflow definition like so it will allow you to trigger your renderer:

{... :emit [[#{:root :items}] (app/default-emitter :main)]}

This basically tells the dataflow to publish changes to [:root :items] as separate rendering deltas under the path [:main :root :items]. In your rendering config you should then specify this path:

[... [:value [:main :root :items] render-items] ...]

You will need to add the rendering path [:main] in a similar way, i.e.

[... [:node-create [:main] render-root] ...]

This will trigger your main template when your rendering deltas start arriving to the renderer.

Hopefully this helps.

like image 37
mdiin Avatar answered Nov 15 '22 07:11

mdiin