NGXS - accessing parent state from child state - ngxs

I have a parent state composed of a child state :
#State({
name: 'parent',
default: { parentProp : 'foo' },
children: [
ChildState,
]
}) class ParentState {}
And a child state :
#State({
name: 'child',
default: { },
}) class ChildState {}
I would like to access parentProp inside ChildState, I tried with the shared state method but it creates a circular dependency as ParentState imports ChildState and vis-versa.
Did I miss a simple solution ?

The simple solution would be to put them in the same file to avoid the circular reference.
That being said, I would ask why the child is so interested in the parent property. Maybe that property could shift down to the child or the child could respond to the same action that the parent uses to set that property to capture its own copy of the value.
If you are looking for a way to create a selector across the two states then you could create a joining selector (see the relevant section here: https://ngxs.gitbook.io/ngxs/concepts/select).

I have exactly the same need as author. The reason why child would be interested in parent property is quite simple.
You focus here mainly on selecting part, but in my case I need it to keep clean files with state, where I'd like to avoid mess.
It's not my case, but corespond with it :). Let say we have main state with some properties and some child states keeping more complex data structure.
And now some action happens which set some valu in main state, then other happen which set something in child state, but I want to set it f.e. in map with key as value of property from main state.
It's nothing spectacular... And such possibility probably would help a lot.

Related

Updating a parent structure reference golang

I am new to Golang. I have this example here - https://go.dev/play/p/lusSZk5be4b
I am trying to update the global parent structure from one of the elements of the same parent structure. I was expecting this program might create an issue because of updating the parent structure from it's own child but this seems to work fine.
I did not understand if this is the right behaviour and is accepted in golang or this kind of updating the parent from child should not be done at all. Any help is appreciated.
Thank you.
You're not actually replacing the parent, but the global variable.
If you keep a reference to the original parent you'll see things remain the same there:
https://go.dev/play/p/FsNVdheZPfE
func main() {
p = &parent{}
oldParent = p
...
fmt.Pritnln(oldParent)
...
Even if you had an actual parent on the child struct and update it (example: https://go.dev/play/p/hELKFB7DWc- ) , the original reference would still have the child, but the child would have a parent with no children.
So in summary, you're just updating references which is totally valid. Whether that makes sense in code or you might lose an important reference that's a different thing.

The Caveats of Sub States?

I am a newbie and hacking around with ngxs.
On the docs There are caveats to Sub States.
This is only intended to work with nested objects, so trying to create stores on nested array objects will not work.
Sub states can only be used once, reuse implies several restrictions that would eliminate some high value features. If you want to re-use them, just create a new state and inherit from it.
I believe I understand the first point to a small degree but I don't fully grasp what the second point means.
Would someone be able to expand on that?
it means that a single state class can't be a child of multiple parent classes. the workaround would be to create new states by extending. so
#State({
name: 'foo' // you can't have another state with this name
})
class MyState1 {}
// so if you want to reuse the listeners and such from 'foo' you have to extend
#State({
name: 'bar'
})
class MyState2 extends MyState1 {}

Implied (hidden) parent state in UI-Router

Suppose I have the following nested UI-Router route:
/parent/{parentId}/child/{childId}
parent:child in my case is a one:many relation, therefore any valid childId implies a specific parentId. I'd like to maintain the nested state in my application, keeping access to parent resolve dependencies without reloading between sibling children; but instead represent the above with the terser URL:
/child/{childId}
Ideally, I'd like UI-Router to do as much of the lifting as possible, and only write the action to recover just the parent state when it is lost (for example when loading the entire page from a child route URL).
My responsibility could, for instance, be simply handling recovery of the parentId state parameter when it is null.
Is this feasible?
edits day 2: It seems, according to the docs, that UI-Router is designed to allow obscuring parent routes from the URL using Absolute Routes. I can only assume that it is supposed to preserve the parent state normally in this case. So, I tried a quick implementation by including two identical URLs, one an absolute URL that is a child state of the parent, and the other that is an actual root state, which does nothing but resolve the parent parameter, then load a controller to perform a redirect to the actual parent/child route. It had lots of problems. I'm trying to determine if I can do the same thing with an abstract state above the parent route. Anyway, suffice to say I haven't solved this yet.

How do I prevent circular references in a hierarchy?

The problem I am trying to solve is to prevent circular references not just between an immediate parent and child, but I also want to ensure that a new child is not already used as a parent somewhere in the hierarchy of records.
I thought I might solve the problem by intercepting the assignment of a parent before executing the code,
self.parent = maybe_the_wrong_choice
and then do important validation before saving the change.
Am I on the right path? If so, how do I grab the old value of an attribute in my Model validation (e.g. self.old_parent) and compare it with the new parent (self.parent) before saving the record?
Thanks in anticipation!
You can get the old parent by self.parent_was and new parent by self.parent.

OO Design Question -- Parent/Child(ren) -- Circular?

I'm fairly new to the OO design process, so please bear with me....
I have two entities that I need to model as classes, call them Parent and Child (it's close enough to the actual problem domain). One Parent will have one or more Children -- I have not interest, in this application, in childless Parents.
Where my brain is going out to lunch is on the fact that I need to be able to find either from the other. In my database I can implement this with a normal foreign key relationship, and the set-based nature of SQL makes it easy to find all Children for a given Parent, or the Parent for a given Child. But as objects...?
I think that the Parent should carry a collection (list, whatever) of Children. I also think that each Child should carry a reference to its Parent. The circular nature of the references, however, is making my head hurt.
Am I:
On the right track?
Completely off base? If so, what should I do differently?
This will almost certainly be implemented in VB.NET, but I'm a ways from cutting code yet.
Edit after 8 answers:
Thanks all. It was hard to pick just one answer to accept.
To clarify a couple of things that were questioned in the answers:
Parent and Child are very different
entities--there's not inheritance
relationship at all. I chose the
names that I did because they're
really very close to the real-world
problem domain, and now see that it's
a source of confusion from an OO
perspective.
The hierarchy is only one level deep--Children will never have Children
within the application.
Thanks again.
The circular references are fine and absolutely standard when creating a tree structure. HTML's Document Object Model (DOM), for example, has the parent and child properties on every node in a DOM tree:
interface Node {
// ...
readonly attribute Node parentNode;
readonly attribute NodeList childNodes;
// ...
}
Sounds like you're on the right track to me. As per your domain model, parents have children and children have parents. You may need to reference each from the other.
There is nothing wrong with circular references, you just have to be careful about what you do with them. Where you'll run into trouble is managing your entities on the server side in an automated fashion when you load them from the database. For example, you fetch a Child object from the database with a query. Do you include the parent information? Do you include the parent's children?
ORM tools like Lightspeed or Microsoft's Entity Framework generally deal with this using "lazy loading" directives. They'll fetch what you need at first (so, when you fetch a Child, it just gets the Child properties and the parent's ID). If later, you dereference the Parent, it goes and fetches the Parent properties and instantiates the Parent object. If later still, you access it's Children collection, it then goes and fetches the relevant child information and creates Child objects for that collection. Until you need them though, it doesn't populate it.
I think it's reasonable to want to be able to traverse the object graph in this way. It's hard to know if you have a justifiable reason for it from your post, but I don't think the references in and of themselves prove a bad design.
I believe you're on the right track. Why is the circular nature of the references making your head hurt? What is the fundamental issue you're having with a Parent having references to its children, and a Child having a reference to its parent?
Are you talking about a class hierarchy, where the parent class knows about its child classes?
You should avoid this at all costs.
By default, a child class knows all about a parent class, because it is an instance of the parent class. But to have a parent class know about its child classes requires that the child class also know all about every other child class. This creates a dependency between one child and every other child of that class. This is an unmaintainable scenario that will cause problems in the future -- if you can even get it to compile or run, which in many languages will not be the case.
That said, it sounds to me like you're not trying to do a class hierarchy, but a collection hierarchy, i.e. a tree. In that case, yes, you're on the right track; it's a common paradigm. The parent node has a collection of child nodes, and the child node has a reference to the parent node.
The thing is? They're all the same class! Here's a very simple example in C#:
public class Node
{
public readonly Node Parent; // null Parent indicates root node
public readonly List<Node> Children = new List<Node>();
public Node(Node parent)
{
Parent = parent;
}
public Node()
{
parent = null;
}
public void AddChild(Node node)
{
Children.Add(node);
}
}
I have a feeling this is what you're really after. Using this paradigm, you would then sub-class Node for whatever nefarious purposes you might have.
If I understand that objects of P contain an array of objects P->c[] representing children. And any node P with no children is a leaf ... with each P containing P->P' (the parent).
The solution you specify, with Parents containing references to children and vice versa eliminates the need to traverse the tree to obtain ancestry of a given child and children of a node. This is really just a tree that can you perform all kinds of links on and algorithms to traverse and enumerate it. Which is fine!
I suggest reading the trees chapter in The Art of Computer Programming for an excellent and in-depth look at tree structures and efficient ways to enumerate parentage and children.
If the children must have a parent I usually just require a parent type instance in the child constructor.
Sounds to me like you're on the path to a bad design. Your architecture should never have circular references.
You should probably re-examine why your children need a reference back to the parent and vice versa. I would lean toward the parent having a collection of children. You can then add functionality to the parent to check to see if a child object is a child of the instance.
A better explination of the goal might be a little more helpful as well...
EDIT
I read up a little more (and listened to comments)...and it turns out I'm quite in the wrong. Circular references do in fact have their place as long as you're careful with them and don't let them get out of hand.

Resources