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

2

6

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

Horatia answered 31/1, 2014 at 11:4 Comment(3)
You might try posting on the pedestal-user mailing list to get help - groups.google.com/forum/#!forum/pedestal-usersUnconformable
I though the 21st century was a nice place, but sure, I'll try and not get answered either there :PHoratia
(Yes, that's a grumpy and childish comment. Just not the right day. Sorry.)Horatia
I
1

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.

Invagination answered 31/1, 2014 at 13:21 Comment(2)
Why would the 'ul' be the template for an item of the list ? Shouldn't it be in another template with 'li's for each item ?Horatia
(I edited my question to show the HTML I want to generate ; I'm starting to wonder what the templates would need to be...)Horatia
F
1

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.

Fantom answered 22/2, 2014 at 8:30 Comment(2)
I don't want a 'main' node added ; I just want to have something emitted on [:root :items] instead of [:root]. I'll see if your solution can be adapted to do that...Horatia
You can omit the argument to app/default-emitter I believe, that would yield what you seek.Fantom

© 2022 - 2024 — McMap. All rights reserved.