Skip to content

Commit 8f64d60

Browse files
committed
first release
1 parent d60670d commit 8f64d60

File tree

75 files changed

+6080
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+6080
-2
lines changed

.gitignore

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/.idea
2+
/vendor
3+
/node_modules
4+
package-lock.json
5+
composer.phar
6+
composer.lock
7+
phpunit.xml
8+
.phpunit.result.cache
9+
.DS_Store
10+
Thumbs.db
11+
yarn.lock
12+
.php-cs-fixer.cache
13+
.npm
14+
.config
15+
.node-gyp
16+
auth.json

README copy.md

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
1. [Requirements](#Requirements)
2+
2. [Installation](#Installation)
3+
3. [Usage](#Usage)
4+
4. [DependsOn](#dependson)
5+
5. [Additional options](#additional-options)
6+
1. [Prefill](#prefill)
7+
2. [Custom Heading](#custom-heading)
8+
6. [Credits](#credits)
9+
10+
## Requirements
11+
12+
- `php: ^7.4 | ^8`
13+
- `laravel/nova: ^4`
14+
15+
## Installation
16+
17+
```
18+
composer require lupennat/nested-form
19+
```
20+
21+
## Usage
22+
23+
Simply add a NestedForm into your fields. The first parameter must be an existing NovaResource class and the second parameter (optional) must be an existing HasOneOrMany relationship in your model.
24+
25+
> NestedForm is visible by deafult on DetailPage, UpdatePage and CreatePage.
26+
> NestedForm is not available on IndexPage.
27+
28+
```php
29+
namespace App\Nova;
30+
31+
use Laravel\Nova\Fields\ID;
32+
use Illuminate\Http\Request;
33+
use Laravel\Nova\Fields\Text;
34+
use Laravel\Nova\Fields\Gravatar;
35+
use Laravel\Nova\Fields\Password;
36+
// Add use statement here.
37+
use Lupennat\NestedForm\NestedForm;
38+
39+
class User extends Resource
40+
{
41+
...
42+
public function fields(Request $request)
43+
{
44+
return [
45+
ID::make()->sortable(),
46+
47+
Gravatar::make(),
48+
49+
Text::make('Name')
50+
->sortable()
51+
->rules('required', 'max:255'),
52+
53+
Text::make('Email')
54+
->sortable()
55+
->rules('required', 'email', 'max:254')
56+
->creationRules('unique:users,email')
57+
->updateRules('unique:users,email,{{resourceId}}'),
58+
59+
Password::make('Password')
60+
->onlyOnForms()
61+
->creationRules('required', 'string', 'min:6')
62+
->updateRules('nullable', 'string', 'min:6'),
63+
64+
// Add NestedForm here.
65+
NestedForm::make('Posts'),
66+
];
67+
}
68+
```
69+
70+
## Depends On
71+
72+
NestedForm support Nova `dependsOn`.
73+
74+
```php
75+
NestedForm::make('Posts', Post::class)
76+
->dependsOn('name', function(NestedForm $field, NovaRequest $novaRequest, FormData $formData) {
77+
if ($formData->name === 'xxx') {
78+
$field->min(1)->max(10);
79+
}
80+
})
81+
```
82+
83+
it also support a short version of dependsOn without callback
84+
85+
```php
86+
NestedForm::make('Posts', Post::class)->dependsOn('name')
87+
```
88+
89+
Both syntax will propagate the condition to related resource, you can access propagated content adding `HasNestedForm` trait on your related resource.
90+
91+
```php
92+
use Lupennat\Nova\Resource;
93+
use Laravel\Nova\Fields\ID;
94+
use Laravel\Nova\Fields\BelongsTo;
95+
use Laravel\Nova\Fields\Select;
96+
use Laravel\Nova\Fields\Text;
97+
use Laravel\Nova\Http\Requests\NovaRequest;
98+
use Lupennat\NestedForm\HasNestedForm;
99+
100+
class Posts extends Resource
101+
{
102+
103+
use HasNestedForm;
104+
105+
public function fields(Request $request)
106+
{
107+
return array_filter([
108+
ID::make(),
109+
BelongsTo::make(__('User'), 'user', User::class),
110+
Select::section(__('Section'), 'section')->options(['sport' => 'Sport', 'news' => 'News'])->rules('required'),
111+
Text::title(__('Title'), 'title')->rules('required'),
112+
$this->canShowExtra() ? Text::make(__('Extra Field'), 'extra')->hide() : null
113+
]);
114+
}
115+
116+
protected function canShowExtra() {
117+
if (
118+
$this->getNestedFormParentResource() === User::uriKey() &&
119+
$this->getNestedFormParentContent('name') === 'xxx'
120+
) {
121+
return true;
122+
}
123+
124+
return false;
125+
}
126+
}
127+
```
128+
129+
## Additional options
130+
131+
| function | description | default |
132+
| ------------------------------ | ------------------------------------------------------ | ------------------------- |
133+
| `->max(int)` | limit number of related resources allowed | 0 |
134+
| `->min(int)` | minimum number of related resources | 0 |
135+
| `->lock()` | disable add and remove related resources | false |
136+
| `->prefill(array,bool)` | [prefill](#prefill) related resources with values | [], false |
137+
| `->useTabs()` | switch display mode to tabs instead of panels | false |
138+
| `->activeTab(int)` | set default active tab by index | 0 |
139+
| `->activeTabByHeading(string)` | set default active tab by 'heading' | null |
140+
| `->canDuplicate()` | enable duplicate resource button | false |
141+
| `->canRestore()` | enable soft delete on resource when deleted (only vue) | false |
142+
| `->addText(string)` | text for add button | "add $resourceName" |
143+
| `->restoreText(string)` | text for restore button | "restore $resourceName" |
144+
| `->removeText(string)` | text for remove button | "remove $resourceName" |
145+
| `->duplicateText(string)` | text for duplicate button | "duplicate $resourceName" |
146+
| `->heading(string, boolean)` | define [custom heading](#custom-heading) | [], false |
147+
| `->separator(string)` | define heading separator | " . " |
148+
149+
### Prefill
150+
151+
You can use `prefill` method to generate a default set of related resource.
152+
153+
> Prefill works only on Create Page
154+
155+
```php
156+
NestedForm::make('Posts', Post::class)
157+
->prefill([
158+
['title' => 'first post', 'section' => 'sport'],
159+
['title' => 'second post', 'section' => 'news'],
160+
])
161+
```
162+
163+
You can force prefill to always respect the numbers of prefilled items through a second boolean parameter.
164+
165+
```php
166+
NestedForm::make('Posts', Post::class)
167+
->prefill([
168+
['title' => 'first post', 'section' => 'sport'],
169+
['title' => 'second post', 'section' => 'news'],
170+
], true)
171+
```
172+
173+
### Custom Heading
174+
175+
By Default NestedForm Heading is:
176+
177+
- DetailPage `${resourceName} ${keyName}: ${resource[keyName]}`
178+
- UpdatePage exists `${resourceName} ${keyName}: ${resource[keyName]}` new `${index} ${separator} ${resourceName}`
179+
- CreatePage `${index} ${separator} ${resourceName}`
180+
181+
You can specify a Custom Heading using resource fields value, defining attribute names, through `heading` method, the second parameter of the method specify if the heading should be "unique".
182+
183+
When a custom heading is defined, the fields are hidden on the panel, but when the user try to add a new resource a modal with required fields is displayed; if unique is true, NestedForm will check to existing related resource the uniqueness of the fields. Multiple fields value will be concatened by the defined separator.
184+
185+
```php
186+
NestedForm::make('Posts', Post::class)
187+
->heading(['section', 'title'], true)
188+
->separator(' - ')
189+
```
190+
191+
---
192+
193+
# Credits
194+
195+
NestedForm field is based on original [Nova Nested Form](https://github.com/yassilah/laravel-nova-nested-form).

0 commit comments

Comments
 (0)