Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Button Field Laravel Package

marshmallow/button-field

A Laravel package that adds a configurable button field to your forms and admin panels. Define labels, links, actions, styles, and confirmation prompts directly in your field definitions, keeping custom actions declarative and consistent with the rest of your form schema.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a single-purpose Nova field that renders a button inside a resource's index, detail, or form views. There is essentially no public documentation and zero dependents, so treat the source as the spec.

  1. Install it:

    composer require marshmallow/button-field
    
  2. Read these files first, in order:

    • composer.json — confirm the Nova version constraint (laravel/nova is usually a require-dev/peer dependency for field packages).
    • src/ — find the field class (typically Button.php) and read its component(), fields(), and any withMeta()/setter methods. Those methods are the API.
    • resources/js/ — read the Vue component to see exactly which props (field.text, field.url, field.target, etc.) are consumed.
    • dist/js/field.js — confirm the built asset exists and that a service provider registers it via Nova::script(...). If there's no provider, you'll need to register/compile assets yourself.
  3. First use case: a "View on site" / "Open record" button on a Nova resource detail page.

    use Marshmallow\ButtonField\Button;
    
    public function fields(NovaRequest $request): array
    {
        return [
            // ...normal fields...
            Button::make('Open')
                ->text('View on site')
                ->url(fn () => $this->resource->publicUrl())
                ->target('_blank')
                ->onlyOnDetail(),
        ];
    }
    

    Verify the exact method names against the source before shipping; the names above are the conventional Nova-field pattern, not documented guarantees.

  4. Sanity check: php artisan nova:check or simply load the resource. If the button doesn't render, the Vue component isn't registered — see Gotchas.

Implementation Patterns

Link-out button (most common). Use a closure for url() so it evaluates per-resource rather than at field-definition time:

Button::make('Stripe')
    ->text('Open in Stripe')
    ->url(fn () => "https://dashboard.stripe.com/customers/{$this->resource->stripe_id}")
    ->target('_blank')
    ->canSee(fn (NovaRequest $request) => $request->user()->isAdmin()),

Index-only action column. Buttons are non-data fields, so scope them deliberately to avoid empty table columns:

Button::make('Actions')
    ->onlyOnIndex()
    ->text('Edit')
    ->url(fn () => Nova::url("/resources/users/{$this->resource->id}/edit")),

Per-row conditional rendering. Combine canSee() with resource state to make the button a status affordance:

->canSee(fn () => $this->resource->status === 'draft')

Compose with Nova's internal router. If the field's component uses <a href>, in-app links trigger a full page load rather than Nova's SPA navigation. If you control the Vue component, emit a click that calls this.$router.push(...); otherwise accept the reload or use it only for external URLs.

Reuse via a helper method. Because there's no config surface, wrap construction in a private method on the resource or a trait so every resource gets consistent text/icon/target behavior:

protected function externalButton(string $label, string $url): Button
{
    return Button::make($label)
        ->text($label)
        ->url($url)
        ->target('_blank')
        ->onlyOnDetail();
}

Passing extra data. Anything not exposed as a fluent setter can go through ->withMeta([...]), then be read in the Vue component as field.<key>. This is the package's real extension point — use it instead of forking if you need an icon, tooltip, or CSS class.

Form-view buttons. A field placed in a create/update form sits inside the <form>. If the Vue component renders a native <button> without type="button", it will submit the form. If you need a form-context button (e.g. "Generate slug"), confirm the type and @click.prevent in the component before relying on it.

Gotchas and Tips

  • Asset registration is the usual failure mode. Nova field packages only work if their compiled JS is registered with Nova::script(). If the button renders as an unknown/blank component, check for a service provider in src/ and that dist/js/field.js is present. Rebuild with npm install && npm run prod if missing.
  • Nova major-version drift. Last release was June 2024. Confirm the laravel/nova constraint supports your installed Nova 4.x/5.x; field components built against older Nova's Vue/Toolkit versions can silently fail on newer majors.
  • Buttons are not data. They are excluded from fillable/validation and are not sortable or searchable. Don't add ->sortable() or ->rules() and expect behavior.
  • withMeta() values must be JSON-serializable. Closures passed into meta (rather than into dedicated setters) will serialize to nothing. Resolve values eagerly or use url(fn () => ...) only if the setter itself accepts callables.
  • Authorization belongs in canSee(). There's no policy integration; a visible button with a sensitive URL leaks the URL to anyone who can view the resource. Gate both visibility and the URL generation.
  • Zero-community risk. With 0 stars and 0 dependents, there's no ecosystem to catch regressions. Pin an exact version in composer.json, and vendor/audit the Vue component if it interpolates resource data into href or v-html (XSS surface).
  • Debugging visibility. If the button doesn't appear, check in this order: field scoping (onlyOnIndex/onlyOnDetail), canSee(), then whether the Vue component name returned by component() matches the registered name — a mismatch fails silently.
  • Extension point is the Vue component. For icons, colors, confirmations, or AJAX behavior, edit resources/js/components/Field.vue locally (after forking or path-repository-ing the package) and consume props via withMeta(). There is no config file or event system to hook into.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package