diff --git a/packages/forms/resources/views/components/text-input.blade.php b/packages/forms/resources/views/components/text-input.blade.php index a67edf1938..8bee9ca020 100644 --- a/packages/forms/resources/views/components/text-input.blade.php +++ b/packages/forms/resources/views/components/text-input.blade.php @@ -62,6 +62,7 @@ 'min' => (! $isConcealed) ? $getMinValue() : null, 'minlength' => (! $isConcealed) ? $getMinLength() : null, 'placeholder' => $getPlaceholder(), + 'readonly' => $isReadOnly(), 'required' => $isRequired() && (! $isConcealed), 'step' => $getStep(), 'type' => $hasMask ? 'text' : $getType(), diff --git a/packages/forms/resources/views/components/textarea.blade.php b/packages/forms/resources/views/components/textarea.blade.php index c1f2dd8cef..ad45d356cb 100644 --- a/packages/forms/resources/views/components/textarea.blade.php +++ b/packages/forms/resources/views/components/textarea.blade.php @@ -30,6 +30,7 @@ 'maxlength' => (! $isConcealed) ? $getMaxLength() : null, 'minlength' => (! $isConcealed) ? $getMinLength() : null, 'placeholder' => $getPlaceholder(), + 'readonly' => $isReadOnly(), 'required' => $isRequired() && (! $isConcealed), 'rows' => $getRows(), $applyStateBindingModifiers('wire:model') => $statePath, diff --git a/packages/forms/src/Components/Concerns/CanBeReadonly.php b/packages/forms/src/Components/Concerns/CanBeReadonly.php new file mode 100644 index 0000000000..85545a6342 --- /dev/null +++ b/packages/forms/src/Components/Concerns/CanBeReadonly.php @@ -0,0 +1,39 @@ +isReadOnly = $condition; + + return $this; + } + + public function readOnlyOn(string | array $contexts): static + { + $this->readOnly(static function (string $context, HasForms $livewire) use ($contexts): bool { + foreach (Arr::wrap($contexts) as $readOnlyContext) { + if ($readOnlyContext === $context || $livewire instanceof $readOnlyContext) { + return true; + } + } + + return false; + }); + + return $this; + } + + public function isReadOnly(): bool + { + return $this->evaluate($this->isReadOnly); + } +} diff --git a/packages/forms/src/Components/TextInput.php b/packages/forms/src/Components/TextInput.php index 0ed5b9f37c..d78d7eb3e8 100644 --- a/packages/forms/src/Components/TextInput.php +++ b/packages/forms/src/Components/TextInput.php @@ -13,6 +13,7 @@ class TextInput extends Field implements Contracts\CanBeLengthConstrained, CanHa use Concerns\CanBeAutocapitalized; use Concerns\CanBeAutocompleted; use Concerns\CanBeLengthConstrained; + use Concerns\CanBeReadOnly; use Concerns\HasAffixes; use Concerns\HasExtraInputAttributes; use Concerns\HasInputMode; diff --git a/packages/forms/src/Components/Textarea.php b/packages/forms/src/Components/Textarea.php index c15f78100f..4f810c35d3 100644 --- a/packages/forms/src/Components/Textarea.php +++ b/packages/forms/src/Components/Textarea.php @@ -10,6 +10,7 @@ class Textarea extends Field implements Contracts\CanBeLengthConstrained use Concerns\CanBeAutocapitalized; use Concerns\CanBeAutocompleted; use Concerns\CanBeLengthConstrained; + use Concerns\CanBeReadOnly; use Concerns\HasExtraInputAttributes; use Concerns\HasPlaceholder; use HasExtraAlpineAttributes; diff --git a/packages/forms/src/Testing/TestsForms.php b/packages/forms/src/Testing/TestsForms.php index 54e2afdf3c..56b5019b00 100644 --- a/packages/forms/src/Testing/TestsForms.php +++ b/packages/forms/src/Testing/TestsForms.php @@ -204,6 +204,29 @@ class TestsForms }; } + public function assertFormFieldIsReadOnly(): Closure + { + return function (string $fieldName, string $formName = 'form'): static { + /** @phpstan-ignore-next-line */ + $this->assertFormFieldExists($fieldName, $formName); + + /** @var ComponentContainer $form */ + $form = $this->instance()->{$formName}; + + /** @var Field $field */ + $field = $form->getFlatFields(withHidden: true)[$fieldName]; + + $livewireClass = $this->instance()::class; + + Assert::assertTrue( + $field->isReadOnly(), + "Failed asserting that a field with the name [{$fieldName}] is read-only on the form named [{$formName}] on the [{$livewireClass}] component." + ); + + return $this; + }; + } + public function assertFormFieldIsHidden(): Closure { return function (string $fieldName, string $formName = 'form'): static {