Custom field dynamic query

Here I have to create a custom field where I have to show suggestion by type [ char and variable name. I want to make it generic where user should pass the query builder and suggest according to the user enter value.
DynamicVairable::make('dynamic_varibale')
->modifyingQuery(function () {
return Notification::query();
})
DynamicVairable::make('dynamic_varibale')
->modifyingQuery(function () {
return Notification::query();
})
But I don't know how to make it dynamic
class DynamicVairable extends Field
{
protected string $view = 'forms.components.variable-field';

public string $text = '';


public Builder |\Closure $modifyingQuery;

public function modifyingQuery(Builder | \Closure $modifyingQuery): static
{
$this->modifyingQuery = $modifyingQuery;

return $this;
}

public function getModifyingQuery()
{
if($this->modifyingQuery instanceof \Closure) {
return ($this->modifyingQuery)();
}
return $this->modifyingQuery;
}

public function searchVariable(string $value)
{
$this->getModifyingQuery()->where('variable', 'like', '%'.$value.'%')->get();
}
}
class DynamicVairable extends Field
{
protected string $view = 'forms.components.variable-field';

public string $text = '';


public Builder |\Closure $modifyingQuery;

public function modifyingQuery(Builder | \Closure $modifyingQuery): static
{
$this->modifyingQuery = $modifyingQuery;

return $this;
}

public function getModifyingQuery()
{
if($this->modifyingQuery instanceof \Closure) {
return ($this->modifyingQuery)();
}
return $this->modifyingQuery;
}

public function searchVariable(string $value)
{
$this->getModifyingQuery()->where('variable', 'like', '%'.$value.'%')->get();
}
}
This is my custom field
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
<input x-model="state">
</div>
</x-dynamic-component>
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
<input x-model="state">
</div>
</x-dynamic-component>
Please suggest some idea I tried with livewire component but from field class I'm not able to pass query builder
2 Replies
Lara Zeus
Lara Zeus3d ago
for Closures add the trait use EvaluatesClosures; and:
public function getModifyingQuery()
{
$this->evaluate($this->modifyingQuery);
}
public function getModifyingQuery()
{
$this->evaluate($this->modifyingQuery);
}
in your livewire version where are calling searchVariable? I think you need an action somehow to trigger it?
Asmit Nepali
Asmit Nepali2d ago
@Lara Zeus Thank you for replying. In livewire version.
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
<livewire:live-varibale x-model="state" :field="$field->getModifyingQuery()"/>
<input x-model="state">
</div>
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
<livewire:live-varibale x-model="state" :field="$field->getModifyingQuery()"/>
<input x-model="state">
</div>
This is my custom field blade file. I want to pass query builder to livewire. But livewire says prototype issue.
<?php
class LiveMention extends Component
{
public Builder $query;
public $variables = [];
public $showVariables = false;
public function mount($query) {
$this->query = $query;
}
public function searchVariables(string $value)
{
$searchString = Str::remove('[', $value);
$this->showVariables = strlen($value) > 0;
$this->variables = $this->query
->where('title', 'like','%'.$searchString.'%')
->get()->map(function($variable) {
return [
'id' => $variable->id,
'title' => $variable->title,
];
});
}

public function triggerVariable($variableName)
{
// Emit the selected variable back to JavaScript
$this->dispatch('triggerVariable', ['title' => $variableName]);
}

public function render()
{
return view('livewire.live-varibale');
}
}
<?php
class LiveMention extends Component
{
public Builder $query;
public $variables = [];
public $showVariables = false;
public function mount($query) {
$this->query = $query;
}
public function searchVariables(string $value)
{
$searchString = Str::remove('[', $value);
$this->showVariables = strlen($value) > 0;
$this->variables = $this->query
->where('title', 'like','%'.$searchString.'%')
->get()->map(function($variable) {
return [
'id' => $variable->id,
'title' => $variable->title,
];
});
}

public function triggerVariable($variableName)
{
// Emit the selected variable back to JavaScript
$this->dispatch('triggerVariable', ['title' => $variableName]);
}

public function render()
{
return view('livewire.live-varibale');
}
}
This is my livewire blade file
<div>
<div
contenteditable="true"
id="editableDiv"
@input="state = $event.target.innerHTML"
@blur="$dispatch('input', $event.target.innerHTML)"
wire:ignore
>
</div>
<input id="hidden-text-box" type="hidden" x-model="state" />

@if($showUserList)
<ul class="bg-white border mt-2 max-h-32 overflow-auto">
//triggerVariable
</ul>
@endif
</div>

@script
<script>
console.log('Livewire component initialized');
let editableDiv = document.getElementById('editableDiv');
let typingTimer; // Timer identifier
const debounceInterval = 300;
editableDiv.addEventListener('input', function () {
console.log('input event triggered');
let content = editableDiv.innerHTML;
let cursorPosition = window.getSelection().focusOffset;
clearTimeout(typingTimer);
let lastAtIndex = content.lastIndexOf('[');
if (lastAtIndex !== -1 && cursorPosition > lastAtIndex + 1) {
let searchTerm = content.substring(lastAtIndex + 1, cursorPosition).trim();
if (searchTerm.length > 0 && !/\s/.test(searchTerm)) {
typingTimer = setTimeout(() => {
$wire.searchVariables(searchTerm);
}, debounceInterval);
}
}
});
Livewire.on('triggerVariable', variable => {
// statements
);
</script>
@endscript
<div>
<div
contenteditable="true"
id="editableDiv"
@input="state = $event.target.innerHTML"
@blur="$dispatch('input', $event.target.innerHTML)"
wire:ignore
>
</div>
<input id="hidden-text-box" type="hidden" x-model="state" />

@if($showUserList)
<ul class="bg-white border mt-2 max-h-32 overflow-auto">
//triggerVariable
</ul>
@endif
</div>

@script
<script>
console.log('Livewire component initialized');
let editableDiv = document.getElementById('editableDiv');
let typingTimer; // Timer identifier
const debounceInterval = 300;
editableDiv.addEventListener('input', function () {
console.log('input event triggered');
let content = editableDiv.innerHTML;
let cursorPosition = window.getSelection().focusOffset;
clearTimeout(typingTimer);
let lastAtIndex = content.lastIndexOf('[');
if (lastAtIndex !== -1 && cursorPosition > lastAtIndex + 1) {
let searchTerm = content.substring(lastAtIndex + 1, cursorPosition).trim();
if (searchTerm.length > 0 && !/\s/.test(searchTerm)) {
typingTimer = setTimeout(() => {
$wire.searchVariables(searchTerm);
}, debounceInterval);
}
}
});
Livewire.on('triggerVariable', variable => {
// statements
);
</script>
@endscript
I want to call searchVariables on change the input field ISSUE: 1. From blade file unable to pass query on livewire class. 2. If I not use livewire then how to call searchVaribales method of blade class from custom field blade file. Note: What I try to do is, Create custom field where I have to add dynamic variables. Anyone have any idea💡
Want results from more Discord servers?
Add your server