I'm using different collections of edges which are switched in CY based on user interactions so in every moment only one of these collections is in CY instance. I need to create new elements in one of this "remote" collections directly from JS object data and I can't figure how to do it other than create new edges with cy.add(eleObjs) and then remove these elements from CY.
Is there a way how to create CY elements from JS object (eleObj) other than with cy.add(eleObj)? I tried eles.add(eleObj) but it doesn't work.
I thought about creating a separate CY instance only for this purpose but I don't know if it's the best solution and one of the problems is that in this case I would also need to synchronize the nodes between CY instances in order to be able to create new edges.
You can think of having a removed node as being analogous to a file being in the trash in your filesystem. You wouldn't create removed nodes, just as you wouldn't create new files in the trash.
Add your elements to the graph, as you normally would. You can set a class with display: none on the elements you don't want displayed. You can also perform layouts on only the subset of the graph that's visible via eles.layout().
Explanation: Having detached elements that are not yet associated with a graph is inconsistent with the model. And creating elements without an associated graph wouldn't buy you any performance gains -- as the elements wouldn't hold anything more than the JSON you already had. And it wouldn't buy you any convenience -- as you couldn't do anything with the elements and cy.add( elesJson ) is just as convenient as cy.add( preexistingEles ).
Related
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.
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.
I have an elm app designed with the Elm Architecture in mind. I've used it for all the samples in the tutorial and they work fine. I have the following components
ContainerListView
ContainerView
AddressView
RegistrationView
...
The ContainerView component is a very formatted div structure that is used to contain other views (but for now, only 1 at a time)
ContainerListView can contain multiple containerViews. It handles their presentation and positioning. You can think of it as an MDI surface
A menu from the main ui is used to add new container views to the container view list.
I'm presented with with three main questions. Two of them are
How do I create the components such that Container view can contain any other element is I pass in for example the init, update, and view functions and expect all things to be wired correctly? At the moment, the samle views I have are kinda hard-coded. They know exactly who the children is.
Some of the components require access to things like url, access token, etc. Does this always have to be passed in from main to the individual components or it can come from another source which will essentially be readonly and maybe updatable only from main?
I'm not sure if these two should be individual questions on their own. Any information on how to architect larger apps beyound hello world will also be appreciated.
I'm working on something similar! Nested controls. I too have a container object which knows about all the types that it can handle, and has basically case statements to handle each type. So I can't drop in a new control type and expect it to handle it, that requires altering the container.
As far as I know elm doesn't have type classes, which would be how I might try to handle that kind of abstraction in haskell or purescript. There's more about that here:
https://github.com/elm-lang/elm-compiler/issues/38
and here:
https://github.com/elm-lang/elm-compiler/issues/1039
The upshot appears to be that they don't know how they want to solve that problem yet, so they haven't.
I have created a cytoscape.js graph. Users are allowed to click and zoom/drill down on any node to see all the neighboring nodes and edges. I need to add a reset button, that will restore the graph to it's original position, i.e. when the page was first loaded. I have tried using a couple of different functions such as cy.load, forcerender, cy.destroy and recreate graph. Only thing left is to clear the entire object from the dom and add another cytoscape graph object. I would like to know if there is a simple way I can do a redraw or reload the entire graph. I have all the details (original styles/node data) stored in an array.
Thanks
Save the positions and then restore them whenever you want with nodes.positions(): http://js.cytoscape.org/#nodes.positions
Or save the element JSONs and then later restore them: http://js.cytoscape.org/#ele.json
I have two columns that I would like to animate separately with a trigger. As I understand it: Skrollr only allows one instantiation on a page. Does anyone know if it's possible to have multiple instances that can be turned off and on?
I've started a working example here:
The grey column will activate the Skrollr instance when clicking on its "Activate!" button. (The "Destroy!" button will remove its instance.)
I would like to isolate the Skrollr animation to just the grey column, but as you can see in this example, the yellow/orange column is also being activated.
Three ways
Remove/add the data attributes between the destroy/init calls and only add them to the elements you want
Use two constants, defined as a function and toggle them between 0 and 1e6 (or something really large). Now the elements with the large one will effectively not be rendered (given you're using edgeStrategy reset)
Monkey patch the refresh method (without touching the skrollr code itself). Skrollr uses it internally when using init. Now you can patch it to use leftColumn.getElementsByTagName('*') or all elements in the right column when no parameter is passed. This way initializing will only affect elements inside one of the columns.