Repeater
A repeater is form layout that allows you to repeat certain fields at a user's request. This allows you to easily create records that belong to a one-to-many relationship, or an embedded array of structs in your underlying model.
Getting Started
You can create a new repeater as so:
FormRepeater("MyRepeater")Common Methods
For a list of common layout component methods, see here.
Schema
A repeater has a schema that is duplicated whenever the user request another entry, or in the case of loading a resource, based on how many elements are in an array.
// The Name and Grade of a student can be duplicated,
// allowing you to specify an array of students to attach to your model.
FormRepeater("Students").
Schema(
FormInput("Name"),
FormSelect("Grade"),
)Relationships
Repeaters make the most sense in the context of relationships or embedded arrays within your form's core model.
Naming your repeater
The name of the repeater must match the exact name of your associated relation or array. See below for additional examples.
Example
Here we have a model of subjects and an embedded model of students. In other words, each subject can have a list of students
type Subject struct {
Name string
StartDate time.Time
EndDate time.Time
Students []Students
}
type Student struct {
Name string
Age int
}In order to edit and control a list of students apart of your Subject, you could create a repeater.
Form(driver).
Schema(
FormInput("Name"),
FormDateTime("StartDate"),
FormDateTime("EndDate"),
// Please note the name is an exact match to our field called Students
FormRepeater("Students").
Schema(
FormInput("Name"),
FormInput("Age").Numeric(),
)
)This will allow you to create dynamically create students, as well as view that relationship and each of it's fields, within your parent model's form!
GORM
This works exactly the same way for GORM based models!
GORM Joins
Iridium's gorm driver will automatically Preload the repeater's relationship based on its name.
For example, if in the above examples, those models were GORM models, Iridium would call query.Preload("Students") for you!
Please see the gorm driver link if you need greater control over how to build your query and relationship.
Deleteable
Deletable allows you to delete repeater elements. It will display a trash can in each repeater element's toolbar.
// Static
FormRepeater("repeater").
Deletable()
// Dynamic
FormRepeater("repeater").
DeletableFn(func (ctx FieldContext) bool {
return true
})Collapsable
Collapsable allows users to collapse their repeater elements. It will display a chevron in each repeater element's toolbar.
// Static
FormRepeater("repeater").
Collapsable()
// Dynamic
FormRepeater("repeater").
CollapsableFn(func (ctx FieldContext) bool {
return true
})Reactivity
Form elements inside a repeater can interact with any other form element using our reactivity hooks.
Pathing Via Index
Repeaters have a hidden index grid that need to be apart of your pathing when using our callbacks. Please see our examples below.
Example
Here is a simple form setup involving a form repeater:
FormInput("City"),
FormRepeater("Students").
Schema(
FormInput("Name"),
FormInput("Grade")
)Pathing inward
You can have the City input interact with a repeater element as so:
FormInput("City").
Live().
AfterStateUpdated(func(state []string, ctx FieldContext) ([]string, error) {
// Please note the index apart of the pathing!
// Update the name of the first repeater
ctx.Set("./Students/0/Name", "Joe Smith")
// Update the name of the second repeater
ctx.Set("./Students/1/Name", "Larry Smith")
return state, nil
})
FormRepeater("Students").
Schema(
FormInput("Name"),
FormInput("Grade")
)Pathing between elements
FormInput("City"),
FormRepeater("Students").
Schema(
FormInput("Name").
Live().
AfterStateUpdated(func(state []string, ctx FieldContext) ([]string, error) {
// Updating the Name of any repeater element will
// cause the `Grade` of the 2nd repeater element to be set
// to "12". (Remember repeaters are 0 based)
ctx.Set("../1/Grade", "12")
// Additionally, it will set the Grade within this repeater element
// to be set to "4"
ctx.Set("Grade", "4")
return state, nil
}),
FormInput("Grade")
)Pathing outwards
FormInput("City"),
FormRepeater("Students").
Schema(
FormInput("Name").
Live().
AfterStateUpdated(func(state []string, ctx FieldContext) ([]string, error) {
// Please note the ../../
// One '..' to escape this repeater card, and another '..'
// to escape the entire repeater
ctx.Set("../../City", "Toronto")
return state, nil
}),
FormInput("Grade")
)