66use Illuminate \Support \Str ;
77use Illuminate \Validation \ValidationException ;
88use Laravel \Nova \Fields \BelongsTo ;
9+ use Laravel \Nova \Fields \BelongsToMany ;
910use Laravel \Nova \Fields \Field ;
1011use Laravel \Nova \Fields \MorphTo ;
1112use Laravel \Nova \Fields \ResourceRelationshipGuesser ;
1213use Laravel \Nova \Http \Controllers \ResourceDestroyController ;
14+ use Laravel \Nova \Http \Controllers \ResourceDetachController ;
1315use Laravel \Nova \Http \Controllers \ResourceStoreController ;
1416use Laravel \Nova \Http \Controllers \ResourceUpdateController ;
1517use Laravel \Nova \Http \Requests \CreateResourceRequest ;
1618use Laravel \Nova \Http \Requests \DeleteResourceRequest ;
19+ use Laravel \Nova \Http \Requests \DetachResourceRequest ;
1720use Laravel \Nova \Http \Requests \NovaRequest ;
1821use Laravel \Nova \Http \Requests \UpdateResourceRequest ;
1922use Laravel \Nova \Nova ;
2023use Laravel \Nova \Panel ;
2124
25+ use function GuzzleHttp \json_encode ;
26+
2227class NestedForm extends Field
2328{
2429
@@ -153,19 +158,6 @@ class NestedForm extends Field
153158 * @var Panel|Field|NestedForm
154159 */
155160 protected $ returnContext ;
156- /**
157- * Indicates if the element should be shown on the index view.
158- *
159- * @var \Closure|bool
160- */
161- public $ showOnIndex = false ;
162-
163- /**
164- * Indicates if the element should be shown on the detail view.
165- *
166- * @var \Closure|bool
167- */
168- public $ showOnDetail = false ;
169161
170162 /**
171163 * Create a new nested form.
@@ -327,10 +319,11 @@ protected function isManyRelationsip()
327319 protected function fillAttributeFromRequest (NovaRequest $ request , $ requestAttribute , $ model , $ attribute )
328320 {
329321 if ($ model ->exists ) {
330- $ children = collect ($ request ->get ($ requestAttribute ));
331- $ request ->route ()->setParameter ('resource ' , $ this ->resourceName );
332- $ this ->deleteChildren ($ request , $ model , $ children );
333- $ this ->createOrUpdateChildren ($ request , $ model , $ children , $ requestAttribute , $ this ->getRelatedKeys ($ request ));
322+ $ newRequest = NovaRequest::createFrom ($ request );
323+ $ children = collect ($ newRequest ->get ($ requestAttribute ));
324+ $ newRequest ->route ()->setParameter ('resource ' , $ this ->resourceName );
325+ $ this ->deleteChildren ($ newRequest , $ model , $ children );
326+ $ this ->createOrUpdateChildren ($ newRequest , $ model , $ children , $ requestAttribute , $ this ->getRelatedKeys ($ newRequest ));
334327 } else {
335328 $ model ::saved (function ($ model ) use ($ request , $ requestAttribute , $ attribute ) {
336329 $ this ->fillAttributeFromRequest ($ request , $ requestAttribute , $ model , $ attribute );
@@ -343,7 +336,7 @@ protected function fillAttributeFromRequest(NovaRequest $request, $requestAttrib
343336 */
344337 public function isRelatedField ($ field )
345338 {
346- if ($ field instanceof BelongsTo) {
339+ if ($ field instanceof BelongsTo || $ field instanceof BelongsToMany ) {
347340 return $ field ->resourceName === $ this ->viaResource ;
348341 } else if ($ field instanceof MorphTo) {
349342 return collect ($ field ->morphToTypes )->pluck ('value ' )->contains ($ this ->viaResource );
@@ -362,7 +355,7 @@ protected function getRelatedKeys(NovaRequest $request)
362355 });
363356
364357 if (!$ field ) {
365- throw new \Exception (__ ('A BelongsTo or MorphTo field needs to be set on your related resource. ' ));
358+ throw new \Exception (__ ('A field defining the inverse relationship needs to be set on your related resource (e.g. MorphTo, BelongsTo, BelongsToMany...) ' ));
366359 }
367360
368361 if ($ field instanceof MorphTo) {
@@ -403,6 +396,10 @@ protected function getValidationErrorAttribute(int $index, string $key)
403396 */
404397 protected function deleteChildren (NovaRequest $ request , $ model , $ children )
405398 {
399+ if ($ this ->getRelationshipType () === 'BelongsToMany ' ) {
400+ return (new ResourceDetachController )->handle ($ this ->getDetachRequest ($ request , $ model , $ children ));
401+ }
402+
406403 return (new ResourceDestroyController )->handle ($ this ->getDeleteRequest ($ request , $ model , $ children ));
407404 }
408405
@@ -440,6 +437,19 @@ protected function updateChild(NovaRequest $request, $model, $child, $index, $re
440437 return (new ResourceUpdateController )->handle ($ this ->getUpdateRequest ($ request , $ model , $ child , $ index , $ requestAttribute , $ relatedKeys ));
441438 }
442439
440+ /**
441+ * Get a request for detach.
442+ */
443+ protected function getDetachRequest (NovaRequest $ request , $ model , $ children )
444+ {
445+ return DetachResourceRequest::createFrom ($ request ->replace ([
446+ 'viaResource ' => $ this ->viaResource ,
447+ 'viaResourceId ' => $ model ->id ,
448+ 'viaRelationship ' => $ this ->viaRelationship ,
449+ 'resources ' => $ model ->{$ this ->viaRelationship }()->select ($ this ->attribute . '. ' . $ this ->keyName )->whereNotIn ($ this ->attribute . '. ' . $ this ->keyName , $ children ->pluck ($ this ->keyName ))->pluck ($ this ->keyName )
450+ ]));
451+ }
452+
443453 /**
444454 * Get a request for delete.
445455 */
0 commit comments