Fork me on GitHub
#fulcro
<
2019-01-28
>
souenzzo11:01:49

I put some "initial data" inside the index.html. just moved from hiccup to fulcro.client.dom-server to generate my index.html. After this move I see that hiccup does not quote things. I was vulnerable to HTML injection attacks.

claudiu12:01:49

@U2J4FRT2T How did you add the intial-data ? did you use the ssr/initial-state->script-tag helper ?

souenzzo12:01:09

šŸ˜® nope. I will look at it. ATM i'm not using SSR. I just generate a simple HTML with a greeting

souenzzo12:01:08

I'm using "transit-string" inside a data-tag I think that it's better then a global JS var...

timeyyy21:01:48

@grant did you make much progress with aws-amplify?

timeyyy22:01:32

I'm trying to get Auth working, it correctly routes to the login screen, but the api calls and styling do not work.

hmaurer22:01:36

What should the query be on a component that displays a list of entities, but where I do not want to tie it to a particular list? For example:

(defsc PersonList [this props]
  {:query [{:person/friends [:person/name]}]}})
with the above definition this component would be tied to ddisplaying a specific list, the personā€™s friends. How can I make a re-usable components to display any list so long at the items satisfy the sub-query :person/name?

wilkerlucio22:01:30

there are a few ways to go about this, the simplest is just have one component for each list, you can even generate then programatically if you need to, I would think if you have that many kinds of list. but if you really want to change that, you can take a look at dynamic queries, with those you can dynamically compute the query, so you can chance as you wish

wilkerlucio22:01:31

can you tell more about for what case you like to keep this variable?

hmaurer22:01:09

@wilkerlucio in think in my scenario having a component per list is perfectly acceptable, in fact right now I will only have one such components. But writing this component begged the question, so I thought I would ask šŸ™‚

wilkerlucio22:01:03

I can understand, its good when you know its possible, even when in reality you will hardly need it šŸ˜›

hmaurer22:01:11

In GraphQL/Relay/Apollo (which I am used to), itā€™s common to have a list component expose a query for the elements (.e.g the PersonList would expose a query for a Person), then whichever component is using that list can compose in the Person query when querying for the list data

hmaurer22:01:14

if you see what I mean

wilkerlucio22:01:53

you still get that, but even on graphql you still have to define the list name in the parent, right? or do you use the list name as a variable too there?

hmaurer22:01:02

Itā€™s taking me a bit of getting used to with Fulcro. Another scenario I was thinking of the other day was a component who needs to display two bits of data that donā€™t live on the same node

wilkerlucio22:01:27

even if they dont you can always make a link to it

wilkerlucio22:01:51

or use some globals, in fulcro your component can point to any global table with the syntax: :query [[:root-table '_]]

hmaurer22:01:57

@wilkerlucio what do you mean by that? The parent might have the list name, yes. So you could have a generic PersonList component, then on the parent use it as <PersonList items={friends} />, where you composed the PersonList.person query when fetching the friend data

wilkerlucio22:01:13

then you :root-table key in the props, with that global value

hmaurer22:01:15

@wilkerlucio ah yes, but I meant generic component (in the same way as the list component here). For example, a generic component to compare two Person objects.

wilkerlucio23:01:30

yup, you could write a component that points to two person instances, you can make up as many names as you want, you just need to make a way to "select" those items, using a mutation for example, you can change the db of a ui component to have the pointers, makes sense?

wilkerlucio23:01:35

something like:

wilkerlucio23:01:37

{:ident [:ui/id :ui/id]
 :query [:ui/id
         {:ui/person-a (fp/get-query Person)}
         {:ui/person-b (fp/get-query Person)}]}

hmaurer23:01:52

@wilkerlucio but for that you would need dynamic queries, right? I get how you can make a component that points to two person instances (given IDs), but you canā€™t pass two instances as props, right?

wilkerlucio23:01:19

no need for dynamic, just a new component to accommodate the relationships

hmaurer23:01:57

but then whatever component is using this ā€œcomparisonā€ component will need to compose the Person query, right? Not the comparison componentā€™s query?

wilkerlucio23:01:51

depends on when you want to setup the relationship

wilkerlucio23:01:09

we can think of a list of products that the user will select to compare

wilkerlucio23:01:19

at first, the compare component will have nothing, because user didn't selected anything

wilkerlucio23:01:40

then by interacting you can make those links, so the component has the correct selection that was driven by the user

wilkerlucio23:01:06

in case the comparison should start there, this means your server must know about it, so you could use pathom to write rules that define to which things it should point

wilkerlucio23:01:34

so in the end is just about giving a name and fulfilling it at appropriated time, makes sense?

hmaurer23:01:29

@wilkerlucio I think I didnā€™t express myself properly. What i meant is this: if you have a hierarchy of 3 nested components, say App > ProductCompare > Product. When you fetch the list of products on App (as part of Appā€™s query), you will need to compose in the query of the Product component. But the App component itself doesnā€™t use the Product component, itā€™s essentially an implementation detail of the ProductCompare component (which App uses). As far as I can see, there is no way for the ProductCompare component to communicate to App the query it needs on a product.

wilkerlucio23:01:01

we are thinking something fundamentally different I guess, lets get concrete, in the case of product compare, some context will have to be known to define which items it should load to compare at first, right? if you can give me a concret case we can work it out

wilkerlucio23:01:45

from what you describe this is what I imagine as a base scaffold:

wilkerlucio23:01:47

(fp/defsc Product
  [this {::keys []}]
  {:ident [:product/id :product/id]
   :query [:product/id :product/name]}
  ...)

(fp/defsc ProductCompare
  [this {::keys []}]
  {:ident [:product.compare-set/id :product.compare-set/id]
   :query [:product.compare-set/id
           {:product.compare-set/left (fp/get-query Product)}
           {:product.compare-set/right (fp/get-query Product)}]}
  ...)

(fp/defsc App
  [this {::keys []}]
  {:ident [:app/id :app/id]
   :query [:app/id
           {:product.compare-set/last-comparison
            (fp/get-query ProductCompare)}]}
  ...)

hmaurer23:01:48

@wilkerlucio Iā€™ll apply your advice of sticking to non-generic components for now; I donā€™t want to waste your time with theoretical discussions if I donā€™t have a specific issue to solve. My specific issue tonight was rendering a generic list, but in my case I can get away with a non-generic list.

wilkerlucio23:01:23

no worries, I find nice to go over those things from time to time šŸ™‚

hmaurer23:01:24

@wilkerlucio ah I see, maybe I am just thinking about this wrong. In the example you gave me you are basically making a ā€œproduct comparisonā€ an actual bit of data

hmaurer23:01:51

I was just thinking of it as two props (the two products) that you pass in, without those two props living on an object (a product comparison)

wilkerlucio23:01:18

yup, because any context needs something to hold it, it could be persistent or not, but at some point you will need something to hold then, its just that fulcro encourages (kind forces :P) you to makes that explicit

hmaurer23:01:59

That makes sense. This solution canā€™t be applied to my ā€œgeneric listā€ issue though, right? i.e. have a PersonList component that I can then use to render a personā€™s friend list, a personā€™s enemies list, etc

wilkerlucio23:01:48

no, you can't, but in practice there is a simple solution, wrap whatever is generic in separated functions and make up more components that look very equal but the list name they are using on their own query

wilkerlucio23:01:21

they get very short and keep things consistent and easy to follow

hmaurer23:01:42

makes sense. So the ā€œspecificā€ list components are basically one-liner excluding the query

wilkerlucio23:01:55

when you make things more dynamic/generic you should also think of the price on navigability, in big code makes that can make a big difference

hmaurer23:01:01

they are only there to query for data and delegate the rendering to the generic function

wilkerlucio23:01:13

exactly šŸ™‚

hmaurer23:01:21

That makes sense. Thanks a lot šŸ™‚

hmaurer23:01:00

@wilkerlucio While I am at it, I have another quick question that came to mind after reading part of the Pathom doc. In Pathom it seems like you have the ability to specify a union-path, so that you can switch over a :type field, for example. In Fulcro unions seem to work differently (based on the table name). Is there a union-path equivalent in Fulcro?

wilkerlucio23:01:22

there is no union-path in fulcro, unions there work in a specific way, based on ident, so you must end up with different idents

wilkerlucio23:01:38

but even in pathom I still use something that's similar to the fulcro idea

wilkerlucio23:01:00

most of the time when I make an union I make the selection to be based on the item having the key associated with the component ident

wilkerlucio23:01:07

works pretty well šŸ™‚