Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ SelectTree::make('categories')
->relationship(relationship: 'categories', titleAttribute: 'name', parentAttribute: 'parent_id', modifyChildQueryUsing: fn($query) => $query));
```

Note: when you filter the parent query, any results found by the child query whose parents have been filtered out will be promoted to root nodes by default (to prevent empty result sets).
To disable this feature, use the `strictNullParentRootNodes()` configuration method

```php
SelectTree::make('categories')
->relationship(relationship: 'categories', titleAttribute: 'name', parentAttribute: 'parent_id', modifyQueryUsing: fn($query) => $query->where('id', 1))
->strictNullParentRootNodes(); // only children of parent results from the parent query will be included in the tree
```


## Methods

Set a custom placeholder when no items are selected
Expand Down
22 changes: 20 additions & 2 deletions src/SelectTree.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class SelectTree extends Field implements HasAffixActions

protected ?Closure $modifyChildQueryUsing = null;

protected Closure|bool $strictNullParentRootNodes = false;

protected Closure|int $defaultOpenLevel = 0;

protected string $direction = 'auto';
Expand Down Expand Up @@ -246,8 +248,11 @@ private function buildTreeFromResults($results, $parent = null): Collection
}
}

// Filter the cache for missing parents in the result set and get the children
$orphanedResults = array_map(
// If the tree has strict rull parent root nodes, only retrieve children whose parent is the null value
// Otherwise, promote other orphaned children to root nodes
$orphanedResults = $this->hasStrictNullParentRootNodes()
? [$parent => $resultCache[$parent]['children']]
: array_map(
fn ($item) => $item['children'],
array_filter(
$resultCache,
Expand All @@ -256,6 +261,7 @@ private function buildTreeFromResults($results, $parent = null): Collection
);

// Move any remaining children from the cache into the root of the tree, since their parents do not show up in the result set

$resultMap[$parent] = [];
foreach ($orphanedResults as $orphanedResult) {
$resultMap[$parent] += $orphanedResult;
Expand Down Expand Up @@ -333,6 +339,13 @@ public function query(Builder|Closure|null $query, string $titleAttribute, strin
return $this;
}

public function strictNullParentRootNodes(Closure|bool $condition = true): static
{
$this->strictNullParentRootNodes = $condition;

return $this;
}

public function withCount(bool $withCount = true): static
{
$this->withCount = $withCount;
Expand Down Expand Up @@ -400,6 +413,11 @@ public function getQuery(): ?Builder
return $this->getRelationship()->getRelated()->query();
}

public function hasStrictNullParentRootNodes(): bool
{
return $this->evaluate($this->strictNullParentRootNodes);
}

public function getTitleAttribute(): string
{
return $this->evaluate($this->titleAttribute);
Expand Down