getChild method
WoFormNode<Object?> ?
getChild({
- required String path,
- required String parentPath,
- required WoFormValues values,
The path of an input is the ids of it and its parents, separated by the character '/'.
Exemple :
InputsNode( id: 'profile', inputs: [ StringInput( id: 'name', ...
The path of the input with id 'name' is '/profile/name'.
Implementation
WoFormNode? getChild({
/// The path of the child, relative to this node (contains this node's id)
required String path,
/// The path until this node
required String parentPath,
required WoFormValues values,
}) {
if (!path.startsWith('/')) {
throw ArgumentError('An input path must start with character "/".');
}
final secondSlashIndex = path.substring(1).indexOf('/');
switch (this) {
case ConditionnalNode(:final condition, :final child):
if (!values.meet(condition)) return null;
// if the path ends at the child of this node
if (secondSlashIndex == -1) {
return (child.id == path.substring(1)) ? child : null;
}
return child.getChild(
path: path.substring(secondSlashIndex + 1),
parentPath: '$parentPath/$id',
values: values,
);
case FutureNode(:final builder):
final snapshot = values.get<AsyncSnapshot<T?>>('$parentPath/$id');
if (snapshot == null) return null;
final child = builder!(snapshot);
final secondSlashIndex = path.substring(1).indexOf('/');
// if the path ends at the child of this node
if (secondSlashIndex == -1) {
return (child.id == path.substring(1)) ? child : null;
}
return child.getChild(
path: path.substring(secondSlashIndex + 1),
parentPath: '$parentPath/$id',
values: values,
);
case DynamicInputsNode():
case InputsNode():
final children = this is InputsNode
? (this as InputsNode).children
: (values['$parentPath/$id'] as List<WoFormNode>?) ?? [];
// if the path ends at the children of this node
if (secondSlashIndex == -1) {
return children.firstWhereOrNull((i) => i.id == path.substring(1));
}
return children
.firstWhereOrNull(
(i) => i.id == path.substring(1, secondSlashIndex + 1),
)
?.getChild(
path: path.substring(secondSlashIndex + 1),
parentPath: '$parentPath/$id',
values: values,
);
case LockerNode(:final child):
// if the path ends at the child of this node
if (secondSlashIndex == -1) {
return (child.id == path.substring(1)) ? child : null;
}
return child.getChild(
path: path.substring(secondSlashIndex + 1),
parentPath: '$parentPath/$id',
values: values,
);
case RootNode(:final children):
assert(
parentPath == '',
'The parentPath of RootNode must always be an empty string.',
);
if (!path.startsWith('/')) {
throw ArgumentError(
'An input path must start with character "/" : $path',
);
}
final secondSlashIndex = path.substring(1).indexOf('/');
// if the path ends at the children of this node
if (secondSlashIndex == -1) {
return children.firstWhereOrNull((i) => i.id == path.substring(1));
}
final firstPathId = path.substring(1, secondSlashIndex + 1);
return children
.firstWhereOrNull(
(
child,
) => child.id == firstPathId,
)
?.getChild(
path: path.substring(secondSlashIndex + 1),
// skip root's id
parentPath: parentPath,
values: values,
);
case PathBuilderNode():
case SelectorNode():
case ValueBuilderNode():
case ValuesBuilderNode():
final child = switch (this) {
PathBuilderNode(:final builder) => builder!(
'$parentPath/$id',
),
SelectorNode(:final selector, :final builder) => builder!(
selector!(values),
),
ValueBuilderNode(:final path, :final builder) => builder!(
values.getValue(path, parentPath: '$parentPath/$id'),
),
ValuesBuilderNode(:final paths, :final builder) => builder!(
{
for (final path in paths)
path: values.getValue(path, parentPath: '$parentPath/$id'),
},
),
_ => throw AssertionError(),
};
// if the path ends at the child of this node
if (secondSlashIndex == -1) {
return (child.id == path.substring(1)) ? child : null;
}
return child.getChild(
path: path.substring(secondSlashIndex + 1),
parentPath: '$parentPath/$id',
values: values,
);
case ValueListenerNode():
case WidgetNode():
case EmptyNode():
return null;
// WoFormInput overrides this method
case WoFormInput():
throw UnimplementedError();
}
}