Giter Club home page Giter Club logo

inertia-phoenix's People

Contributors

anonychun avatar derrickreimer avatar osbre avatar oscar345 avatar tayjohno avatar tonydangblog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

inertia-phoenix's Issues

No loader is configured for ".svelte" files

Hi! I tried running this with Svelte, however, I was greeted with these errors. And after a little bit digging, it turns out the default ESBUILD configuration in Phoenix doesn't support plugins (which is needed for SVELTE support). Is my assumption correct that a custom build step is needed, such as Webpack?

[watch] build finished, watching for changes...
✘ [ERROR] No loader is configured for ".svelte" files: node_modules/@inertiajs/svelte/src/Link.svelte

    node_modules/@inertiajs/svelte/src/index.js:2:32:
      2 │ export { default as Link } from './Link.svelte'
        ╵                                 ~~~~~~~~~~~~~~~

✘ [ERROR] No loader is configured for ".svelte" files: node_modules/@inertiajs/svelte/src/App.svelte

    node_modules/@inertiajs/svelte/src/createInertiaApp.js:2:16:
      2 │ import App from './App.svelte'
        ╵                 ~~~~~~~~~~~~~~

✘ [ERROR] No loader is configured for ".svelte" files: node_modules/@inertiajs/svelte/src/SSR.svelte

    node_modules/@inertiajs/svelte/src/createInertiaApp.js:3:16:
      3 │ import SSR from './SSR.svelte'
        ╵                 ~~~~~~~~~~~~~~

My app.js looks like this:

import { createInertiaApp } from '@inertiajs/svelte'

createInertiaApp({
    resolve: name => {
      const pages = import(`./pages/${name}.svelte`)
      return pages[`./pages/${name}.svelte`]
    },
    setup({ el, App, props }) {
      new App({ target: el, props })
    },
})```

[Question] Setting up the client side for a phoenix application

Hey, sorry if this isn't the best place to ask. I'm just trying out various inertia packages for phoenix.

I'm just wondering, do you guys use esbuild that comes preinstalled in a phoenix application? And if so, how do you configure the client side part of inertia with it? Particularly around dynamically importing of the pages.

Form error handling

Hi again, so far the library looks great! Thanks for your hard work. Maybe this is more of information than being an issue itself, but when working with forms, I noticed that the form object isn't being populated with the errors from the backend.

My product_controller.ex

def create(conn, %{"product" => product_params}) do
    case Storefront.create_product(product_params) do
      {:ok, _product} ->
        conn
        |> put_flash(:info, "Product created successfully.")
        |> redirect(to: ~p"/storefront/products")

      {:error, %Ecto.Changeset{} = changeset} ->
        IO.inspect changeset
        conn
        |> assign_errors(changeset)
        |> redirect(to: ~p"/storefront/products/new")
    end
end

My frontend looks like this.

Inside custom_form.svelte:

<form action={action} method={method} on:submit|preventDefault={handleSubmit}>
     <h1 class="text-2xl">
         Create Product
     </h1>
     <p class="mt-1 text-sm text-gray-500">
         Input details below to create product
     </p>
    <div class="mt-1">
         <Input errors={errors.name} name="product[name]" value="" />
    </div>
    ...
</form>
<script>
    import { onMount } from 'svelte';
    import { useForm } from '@inertiajs/svelte'
    import { page } from '@inertiajs/svelte'

    export let method = 'post'
    export let action = '/storefront/products'
    export let errors = {}

    let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")

    let form = useForm({
        _csrf_token: csrfToken,
        product: {
            name: null,
            price: null,
            description: null,
            features: null,
        }
    })

    function handleSubmit() {
        $form.post(action)
    }

    onMount(() => {
        errors = $page.props.errors
        errors = errors
        console.log(errors) // returns {}
        console.log($form.errors) // returns {}
        console.log(form.errors) // returns undefined
    });
</script>

Inside my input.svelte :

<div phx-feedback-for={name}>
    <input name={name} value={value} type={type} class={normalClasses}/>
    {#if errors}
        <p class="mt-1 gap-3 text-sm leading-6 text-rose-600">
            <span class="hero-exclamation-circle-mini mt-0.5 w-5 h-5 flex-none"></span>
            {errors}
        </p>
    {/if}
</div>

<script>
    import { onMount } from "svelte";

    export let name
    export let errors
    export let value
    export let type = "text"
    
    let normalClasses = "shadow-sm focus:ring-zinc-300 focus:border-zinc-400"
</script>

And finally, inside the new template at /storefront/products/new:

<CustomForm/>

This setup works perfectly fine. My only query is, the $form object is not populated with the errors, but rather it is being set at $page.props.errors. My controller has defined |> assign_errors(changeset) too as shown above.
I checked the documentation at https://inertiajs.com/forms and it seems like from their example, this should work:

{#if $form.errors.email}
  <div>{$form.errors.email}</div>
{/if}

But, it does not. I can actually see the errors populated inside the data attribute of the div with id app too:
image

Is this expected behaviour or am I doing something wrong?

I consulted the readme, the corresponding pull request #10 and even the other repo which another commenter mentioned previously at https://github.com/tonydangblog/phoenix-inertia-svelte.
It seems to me like the $form object should be populated as per Inertia's own documentation at https://inertiajs.com/forms.

Again, thanks for the wonderful project.
Thanks!

Error propagation

We should add official support for propagating errors back to the Inertia client-side.

In order for your server-side validation errors to be available client-side, your server-side framework must share them via the errors prop. Inertia's first-party adapters, such as the Laravel adapter, do this automatically. For other frameworks, you may need to do this manually. Please refer to your specific server-side adapter documentation for more information.

https://inertiajs.com/validation

From a little type sleuthing, Inertia expects the props to contain errors:

https://github.com/inertiajs/inertia/blob/683155c8639aef8dc812c3fab4cdb5e2a35eccde/packages/core/src/types.ts#L31-L44

Errors and ErrorBag take the following shape:

https://github.com/inertiajs/inertia/blob/683155c8639aef8dc812c3fab4cdb5e2a35eccde/packages/core/src/types.ts#L9-L10

My thinking is we should add an assign_errors helper that accepts either an Ecto.Changeset or a bare map (that complies with the expected shapes). The helper should also be aware of the "error bag" specified in the request header (https://inertiajs.com/validation#error-bags).

Example

Given a request like this:

router.post('/companies', data, {
  errorBag: 'createCompany',
})

The incoming request should contain the error bag header (handled by Inertia):

X-Inertia-Error-Bag: createCompany

And if the request failed, we could set errors like this:

conn
|> assign_errors(changeset)

Which would result in the props containing errors automatically serialized and scoped under the proper bag name pulled from request headers:

{
  "props": {
    "errors": {
      "createCompany": {
        "name": "Name is required"
      }
    }
  }
}

Lazy data evaluation

This is needed for #6, so that we can conditionally compute props only if they are needed.

We should accept functions for prop values in both modes for prop-setting: assign_prop and the props argument on render_inertia.

conn
|> assign_prop(:users, fn -> User.list() end)
|> render_inertia("Page", %{expensive thing: fn -> calculate() end})

assign_errors does not support nested associations?

Hi, it's me again. It seems like assign_errors does not work for nested associations, unless I am doing something wrong:

#Ecto.Changeset<
  action: :insert,
  changes: %{
    media: [],
    specifications: [
      #Ecto.Changeset<
        action: :insert,
        changes: %{delete: false},
        errors: [
          name: {"can't be blank", [validation: :required]},
          value: {"can't be blank", [validation: :required]}
        ],
        data: #Acme.Storefront.Product.Specification<>,
        valid?: false
      >,
      #Ecto.Changeset<
        action: :insert,
        changes: %{delete: false},
        errors: [
          name: {"can't be blank", [validation: :required]},
          value: {"can't be blank", [validation: :required]}
        ],
        data: #Acme.Storefront.Product.Specification<>,
        valid?: false
      >,
      #Ecto.Changeset<
        action: :insert,
        changes: %{delete: false},
        errors: [
          name: {"can't be blank", [validation: :required]},
          value: {"can't be blank", [validation: :required]}
        ],
        data: #Acme.Storefront.Product.Specification<>,
        valid?: false
      >
    ]
  },
  errors: [
    shipping_options: {"is invalid", [type: {:array, :map}]},
    name: {"can't be blank", [validation: :required]},
    description: {"can't be blank", [validation: :required]},
    slug: {"can't be blank", [validation: :required]},
    price: {"can't be blank", [validation: :required]}
  ],
  data: #Acme.Storefront.Product<>,
  valid?: false
>
image

This is what the XHR response looks like. I guess I can write an Enum.reduce for each of the nested entity with errors and assign it to the conn, but just wanted to check if this is the only way as of now?

Thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.