Skip to main content
Firstlight / NativePHP

Firstlight / Docs

Native controls, Laravel validate/submit/authorize on native screens, and how Firstlight complements NativePHP Mobile UI.

View source
Authorize Firstlight actions

Authorize Firstlight Actions

Extend FirstlightUI\NativeComponent (or use AuthorizesActions) so a screen can evaluate the current Laravel Gate or Policy before publishing or performing an action:

use App\Models\Post;
use FirstlightUI\NativeComponent;

class PostScreen extends NativeComponent
{
    public Post $post;
    public bool $confirmingDeletion = false;

    public function updatePost(): void
    {
        if (! $this->authorize('update', $this->post)) {
            return;
        }

        $this->post->save();
    }
}

allows() and denies() return booleans. authorize() also returns a boolean; unlike Laravel's throwing Gate method, a denial publishes danger Feedback with This action is unauthorized. and returns false. Keep the guard at the start of every PHP action, even when the published control is already hidden or disabled, because authorization can change after a frame is published.

Choose hide or disable

Hide an ordinary action when its absence is unsurprising:

@if ($this->allows('edit', $post))
    <firstlight:button @press="editPost">
        Edit post
    </firstlight:button>
@endif

Disable an action when preserving its location helps explain the available workflow:

<firstlight:list-item
    headline="Publishing settings"
    supporting="Only editors can change publication access"
    :disabled="$this->denies('update', $post)"
    @press="openPublishingSettings"
/>

Button, Icon Button, and List Item all accept the existing disabled prop. Firstlight does not add a can attribute or evaluate authorization in a native renderer.

Keep destructive actions visible

Never silently omit a destructive action. Keep the Button, Icon Button, or List Item visible and disable it when denied. Supporting copy should explain why the action is unavailable when the surrounding interface does not make that clear.

<firstlight:button
    variant="destructive"
    :disabled="$this->denies('delete', $post)"
    @press="requestDeletion"
>
    Delete post
</firstlight:button>

Confirmation Dialog has no disabled or loading prop. Authorize before setting its visible state, and authorize again when confirmation arrives:

public function requestDeletion(): void
{
    if (! $this->authorize('delete', $this->post)) {
        $this->confirmingDeletion = false;

        return;
    }

    $this->confirmingDeletion = true;
}

public function deletePost(): void
{
    $this->confirmingDeletion = false;

    if (! $this->authorize('delete', $this->post)) {
        return;
    }

    $this->post->delete();
}

public function cancelDeletion(): void
{
    $this->confirmingDeletion = false;
}
<firstlight:confirmation-dialog
    :visible="$confirmingDeletion"
    title="Delete post?"
    message="This action cannot be undone."
    confirm-label="Delete"
    cancel-label="Keep post"
    tone="destructive"
    @press="deletePost"
    @dismiss="cancelDeletion"
/>

The denied request does not open the dialog, and authorize() supplies danger Feedback instead of allowing an uncaught AuthorizationException to reach NativePHP's error overlay.

For deleting rows from an accumulated $listItems collection by stable key, use Destroy list items.

Served from firstlightui/nativephp and cached for a fast first read.