Can global <style> be made to update in response to a subscription update, like normal elements in <body>? - re-frame

In re-frame, components will be automatically updated when a subscription they deref has an update. This is generally used for all kinds of dom elements under a single element (in general a div) somewhere under html>body.
I would like to do the same for style that lives under html>head, i.e. the style should be updated in response to subscription updates.
The spade library allows one to define
"global" style, which is easy to setup once and for all
inline style, which is generated in the react/reagent component's render function and as such can be updated based on subscriptions *)
Now I would like to define style that is not inline, yet is reactive to subscriptions. How can this be done?
My best idea currently is to try to call (reagent.dom/render [my-style] head-el) a second time (in addition to the main rendering done to that div under html>body). Not sure if that is possible or idiomatic.
*) Although only (defattrs) is strictly speaking "inline style" (i.e. something like <elem style=...>), the other option (defclass) (being rendered as <elem class=...> with a corresponding style definition under html>head) is similar in that the style is always updated together with the element, i.e. I cannot seem to update the style of the class separately from rendering the element, e.g. one subscription leads to element changes, whereas another subscription leads to style changes (only).

Related

Vue slot is not working in rare and unpredictable cases (potential vue bug?)

I have this weird bug with a slot that is unreliable in certain unknown cases.
Components
There are 3 hierarchical components.
The grandchild (headlessTable), which offers a slot named arrayValue.
The child (collapsableCard), which passes the slot between grandchild and parent.
The parent (orderDataCard), who decides to render a link for that slot.
Problem: Instead of rendering the link of the parent, the default slot html of the child is being rendered when new data is loaded.
Datastructure (orderDetails)
process (obj)
mark (string)
common (obj)
additionalArguments (array)
category (string)
type (string)
name (string)
value (string)
salesOrganisation (obj)
invoices (array)
invoiceAgreementId (string)
paymentType (string)
Reproduction
Stackblitz or Codesandbox
Please look at the field additionalArguments, it contains a link.
Press ALT+M to simulate fetching new data. Now, instead of rendering a link, the default slot html for that named slot is rendered instead.
You can press ALT+J to load the original data, but this time there's no link.
Initial data (ALT+J)
Loaded data (ALT+M)
Type
Equal value
mark
str
false
common
common
obj
true
salesOrganisation
salesOrganisation
obj
true
invoices (empty)
invoices
arr
false
How 2 resolve
if you uncomment line 68 in app.js (or line 73 in App.vue if you're on codesandbox), which is the field called mark
if invoices is not initially empty in app.js
if mark is removed from html in orderDataCard
if salesOrganisation is removed from html in orderDataCard
if the html in the v-for template section for invoiceItems is empty in orderDataCard
Obviously, these are not solutions.
Notes
In any case, there is no dependence or anything between any of the fields, so it's hard for me to understand why this happens and I suspect this to be a bug with vue. I already created an issue for this. However, devs won't look at the reproduction, because they think it's not minimal as #lines > 100. As soon as I delete any more meaningful lines, the bug is resolved and the removed code is not faulty, so it's very frustrating to work on this. I could still remove lines that are not meaningful, but that would make it more difficult for everyone involved to understand what data is being rendered.
Is anyone able to acknowledge the fact that this is a problem with vue and that the code is not reducible OR (I would prefer this) is anyone able to fix this?
The problem is linked to Vue handling of multiple instances of the same component. In OrderDataCard.vue you have two instances of Collapsable-Card without unique keys. In this case:
Vue uses an algorithm that minimizes element movement and tries to
patch/reuse elements of the same type in-place as much as possible.
I don't quite know how these algorithms work, and why, apparently, it reused the second instance (without a defined slot content), but, setting a unique key for these components solved the issue.
See the working code sandbox: https://codesandbox.io/s/admiring-hamilton-5ytpp?file=/src/components/OrderDataCard.vue:133-149.
Note: I couldn't trigger keyboard events in my browser, so I triggered them on button click.
This may not be the solution, but could help find it:
Objects
I noticed you are working with objects and turning them into arrays. Objects properties can be problematic to work with, because unlike arrays updated properties are not propagated. This is a problem with JavaScript, not Vue. Vue was only possible because of observers introduced, but objects are still not part of that.
You might run into problems when an object is partially updated.
I would suggest looking at Vue.set.
Old code of mine invokes it explicitly by window.Vue.set() for changes in object properties so Vue can propagate them correctly.
That is kind of a bug in Vue, but again stems from JavaScript itself.
Computed arrays
I'm not entirely sure but the computed arrays don't save the above issue with working with objects.
I would go the safe route and use Vue.set() when updating objects and object properties. You can still use the computed arrays then.
Otherwise the obvious: Make real arrays out of the objects instead of working with objects half the time.
this.process
Is there a good reason you are using this.process explicitly instead of the component's props? Or is that a component from a library?
Slots
Have you tried the exact same code but without using the collapsable-card? Just output the link itself? It might point to slot problems in the collapsable-card component. Maybe also partially because of the objects thing from above.

Vue components hierarchy and passing data

I'm writing an app in Vue and I have a really hard time understanding the component hierarchy, namely the parent-child relationships and how to pass data around.
I have a view that contains a map which in turn has some navigation controls and options that are overlayed on top of the map. Now, I want these controls to manipulate the map WITHOUT having to nest the buttons inside the actual maps as it will cause severe display issues (for example, clicking on a zoom button falls through the button and also clicks the next element under it).
My app looks like this:
Mapview
Map
Controls
Options
Optionpanel1
Optionpanel2
...
Now, a HTML input element in Optionpanel1 needs to control something in the Map, which is not actually it's parent component. Also, some data from Map needs to be passed down to Optionpanel1 so it would know what to control. To make matters worse, something in Options also needs to pass something down to Optionpanel1, so, even though event bus would allow communication upwards, it would not solve that I need to pass data from parents to indirect children and also components that are not it's children.
I can actually pass the required property down the line if I nest the Options inside Map and pass it down with :myProp="prop" and then in Options, declare it in props and bind to Optionpanel1, where it is again declared as a prop. But as I mentioned earlier, nesting elements that I do not want to be nested in a visual sense causes massive issues like mouse click falling through. Do elements even need to be nested inside eachother in order to define parent-child relationship?
I would want components to exchange read-only data without Y being a child of X in the DOM. Also, even if nesting components like this would not cause visual issues, does it not seem very annoying to have to register and bind it in every component along the way?
I don't understand why is it so difficult to simply read something from another component. It's starting to seem that Vue is causing a problem that it's supposed to solve? Am I missing something here or am I looking at this in a completely wrong way?
Thanks in advance.
Basically you have 2 options to control complex components:
Handle the actions in your so-called "smart component" (in terms of React), which is the common ancestor for the controlling and controlled components. It's a pretty good solution for small components, but that's not the case.
To separate common logic and data in a Vuex store. I'd recommend you doing this.

RiotJS mounting tag without subtags

I am using tag-based routing with RiotJS. If the tag in the route contains an other tag, it is automatically mounted. Which is great in some cases. But there are cases when I need to pass some options to the tag being mounted, that can't be passed as tag property. I know that this.tags will contain them and I have the means to pass that parameter afterward. But I still am curious if there is a way to stop RiotJS automounting some subtags.
Sounds like you have a design error.
Remember that a tag can contain any classic JS code; you can simply write a logic that populates the tag in any time, way, shape or form. You can also hide it's content via the if condition until it is populated, while it is mounted. You can also hide it in the parent and prevent its mounting in the same manner if you so desire.

How would you abstract this functionality?

Observe the following classes and their containment:
Section has an ItemList which has many Items
But lets say an Item is rendered a different color based on some complicated algorithm that is based off the Section.name it is contained in.
What's the proper/best way to go about abstracting this functionality? Is there a common design pattern that occurs in situations like these? Or is the inherent design flawed?
You should separate your data structures/models from your logic and processing of them. That said, I would make your Item have a Section reference on it referencing it's Section, when you add an Item to the ItemList, ensure the add method looks at the ItemLists Section (parent) and sets the reference on the Item. Same goes for the setter on the ItemList in the Section, it would have to iterate each Item and set the Section.
Alternatively, you could make the Section set on the getter of the ItemList as lazy semantics, that would be entirely up to you depending on the use of your Section the performance statistics would be different between these two approaches.
Further, I would write some form of renderer that took an Item and knew how to render it which would look at the Section on the Item and the Name on that Section.
You may want to render an entire section, but I would write that renderer separate and it would use the ItemRenderer to render each Item.
As an aside, you may want to use a form of IObservableCollection and have the Item implement INotifyPropertyChanged as well so that you could then maintain synchrony both between the rendered version and the item, and synchronize the Item with the Section it exists in by an event registration that updates the Section property appropriately.
What does the rendering? If it's something in Section, or outside of all of these, but accessing the Items from the Section, then there's nothing more needed.
If it's in Item, then you just need to make sure Item knows what Section it belongs to, or can obtain it (e.g. by having an ID it can look up on - useful with languages that make dealing with circular references tricky, but not needless hassle otherwise).
Since the first case causes no difficulty, it's clearly to be preferred over the second, so the closest to a design-pattern is that if you find yourself doing this sort of work in the contained item, to try and move it up to the container, or outside of them all. Beyond that, there isn't much of a problem to need solving.
I would build an ItemRenderer class that knows the algorithm, and pass in the references to each Item you would like to render and the Section it was contained in.
It may also make sense to let each Item know the section it belongs to, but I would still let the ItemRenderer handle the rendering.

Coldfusion object inheritance sanity check needed

I need to know if I am going about something the right way.
For a given page, I am instantiating an object for the page itself. Let's call that object myPage. Within the page I have containers (usually div tags). When I go to an admin component to work with a specific div, I instantiate an object for that as well. Let's call that myDiv.
Now, one of the things I want to work with for a given div is the styling of that div. So normally I would think that I'd just put in some style-related methods, such as myDiv.getPadding() or myDiv.getBackgroundColor(), etc.
But it occurs to me that I may eventually have other objects for which I may also need to do style-related stuff.
Given this, should I then create a separate style.cfc? Would that then be extended by the div object? Or would the style object extend the div object? My understanding is that the more specific object extends the less specific one, but I am not sure which is more specific in this case: is it the div object, which references a specific div, or the style object, which provides a specific set of data?
Thanks in advance!
First, unless you need to write styles on-the-fly, I would create one or more stylesheets and link them dynamically, instead of creating them dynamically.
Assuming, however, that you do need to create them on-the-fly...
I would not have either the control (div) extend the style or vice-versa. A style is not a more specific definition of a div, nor is the reverse true. What I would do is create a style object that only contains the display meta-data for a given element or element set. This can be contained within your control/div object (not an extension), or can be part of the page object. The style is definitely related to the control, but I would not combine them, as that makes it harder to separate content and presentation.
By no means am I saying this is the best approach, but if you really wanted to use CFCs to style your pages, you could have a DivTag.cfc extend an HtmlTag.cfc, which would act as your base class for all HTML tags. You could then compose a StyleAttribute.cfc into your HtmlTag.cfc to work with any style properties, such as background colors and padding. So then you would end up calling functions like myDiv.getStyle().getPadding().
In general, you should really try to favor composition ("has a") over inheritance ("is a") and not get too crazy with your component hierarchies. In this case, I'd recommend using CSS files to style your pages.