echo icon indicating copy to clipboard operation
echo copied to clipboard

Bind formdata with array input.

Open mytc opened this issue 5 years ago • 7 comments

I having having problem with binding the form data. The input would be like this

<input name="codes[1][icode]" type="number" />
<input name="codes[1][limit]" type="text" />
<input name="codes[2][icode]" type="number" />
<input name="codes[2][limit]" type="text" />

And the struct

type Event struct {
	gorm.Model
	Code []InvideCode `form:"codes"`
}


type InvideCode struct {
	gorm.Model
	EventID uint 
	Code string `form:"icode"`
	Limit string `form:"limit"`
}

And i bind it with event := new(Event) or c.FormValue("codes")

Both give me the empty value. What did I done wrong?

Actually there is similar problem was asked at SO , the accepted answer is using 3rd party library and I don't like it. I wonder if there any Echo way to do it.

mytc avatar Sep 29 '20 18:09 mytc

This issue has been automatically marked as stale because it has not had recent activity. It will be closed within a month if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Dec 25 '20 13:12 stale[bot]

Data binding was improved with Echo v4.2. Please check the docs for request binding Please close if this is resolved for you @mytc

lammel avatar Mar 09 '21 12:03 lammel

The latest several versions of Echo supports this behavior like the following:

type Event struct {
	gorm.Model
	Code []InvideCode `form:"codes[]"`
}

kidlj avatar Jun 17 '22 06:06 kidlj

The latest several versions of Echo supports this behavior like the following:

type Event struct {
	gorm.Model
	Code []InvideCode `form:"codes[]"`
}

It returned an empty array

dovoselly avatar Jun 17 '22 07:06 dovoselly

The latest several versions of Echo supports this behavior like the following:

type Event struct {
	gorm.Model
	Code []InvideCode `form:"codes[]"`
}

It returned an empty array

I haven't read the source code of Echo for this part, but it works for my slightly different cases:

<form>
			<div class="items">
				{{range .Names}}
				<input type="checkbox" id="{{.ID}}" name="ids[]" value={{.ID}} hidden>
				<label for="{{.ID}}">{{.Name}}</label>
				{{end}}
			</div>
</form>

With this handler:

type examPayload struct {
	IDs []int `form:"ids[]"`
}

func (h *Handler) createExam(c echo.Context) error {
	payload := new(examPayload)
	err := c.Bind(payload)
	if err != nil {
		return echo.ErrBadRequest
	}

	if len(payload.IDs) == 0 {
		return echo.ErrBadRequest
	}

	u, err := h.userService.GetUserFromContext(c)
	if err != nil {
		return echo.ErrUnauthorized
	}

	exam, err := h.service.CreateExam(c.Request().Context(), u.ID, payload.IDs)
	if err != nil {
		return echo.ErrInternalServerError
	}

	return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/exam?id=%d", exam.ID))
}

I didn't test for op's case, sorry.

kidlj avatar Jun 17 '22 15:06 kidlj

Echo supports binding data to slices when form value is named codes[] but not codes[N] where N is "dynamic" in form value name.

When you post

<input name="codes[1][icode]" type="number" />
<input name="codes[1][limit]" type="text" />
<input name="codes[2][icode]" type="number" />
<input name="codes[2][limit]" type="text" />

What Echo sees from Request is 4 different form values with following names:

  • codes[1][icode]
  • codes[1][limit]
  • codes[2][icode]
  • codes[2][limit]

There is no (currently) built in magic to guess from brackets and number if it is suppose to be array of things. I am quite sure there are plenty of libraries that can extract form values from Go standard library Request struct like that (Echo is built on Go standard library Request struct)

aldas avatar Jun 17 '22 18:06 aldas

you can use https://pkg.go.dev/github.com/go-playground/form/[email protected]#Decoder.Decode to bind data to struct not map. It seems that there is no magic like laravel to parse formdata.

Septrum101 avatar Jul 14 '22 04:07 Septrum101