diff --git a/docs/docsrc/examples/examples_presets/detailing_inline_edit.go b/docs/docsrc/examples/examples_presets/detailing_inline_edit.go index 6d01a29ae..6386bda25 100644 --- a/docs/docsrc/examples/examples_presets/detailing_inline_edit.go +++ b/docs/docsrc/examples/examples_presets/detailing_inline_edit.go @@ -105,6 +105,32 @@ func PresetsDetailInlineEditInspectTables(b *presets.Builder, db *gorm.DB) ( return } +func PresetsDetailInlineEditValidate(b *presets.Builder, db *gorm.DB) ( + cust *presets.ModelBuilder, + cl *presets.ListingBuilder, + ce *presets.EditingBuilder, + dp *presets.DetailingBuilder, +) { + err := db.AutoMigrate(&Customer{}, &CreditCard{}, &Note{}) + if err != nil { + panic(err) + } + b.DataOperator(gorm2op.DataOperator(db)) + + cust = b.Model(&Customer{}) + // This should inspect Notes attributes, When it is a list, It should show a standard table in detail page + dp = cust.Detailing("name_section").Drawer(true) + dp.Section("name_section").Label("name must not be empty").Editing("Name").Viewing("Name").Validator(func(obj interface{}, ctx *web.EventContext) (err web.ValidationErrors) { + customer := obj.(*Customer) + if customer.Name == "" { + err.GlobalError("customer name must not be empty") + } + return + }) + + return +} + func PresetsDetailNestedMany(b *presets.Builder, db *gorm.DB) ( mb *presets.ModelBuilder, cl *presets.ListingBuilder, diff --git a/docs/docsrc/examples/examples_presets/detailing_test.go b/docs/docsrc/examples/examples_presets/detailing_test.go index c7481c154..b80635e02 100644 --- a/docs/docsrc/examples/examples_presets/detailing_test.go +++ b/docs/docsrc/examples/examples_presets/detailing_test.go @@ -210,3 +210,29 @@ func TestPresetsDetailActionsComponent(t *testing.T) { }) } } + +func TestPresetsDetailSectionValidate(t *testing.T) { + pb := presets.New().DataOperator(gorm2op.DataOperator(TestDB)) + PresetsDetailInlineEditValidate(pb, TestDB) + + cases := []multipartestutils.TestCase{ + { + Name: "page detail show", + Debug: true, + ReqFunc: func() *http.Request { + detailData.TruncatePut(SqlDB) + return multipartestutils.NewMultipartBuilder(). + PageURL("/customers?__execute_event__=presets_Detailing_Field_Save&detailField=name_section&id=12"). + AddField("name_section.Name", ""). + BuildEventFuncRequest() + }, + ExpectRunScriptContainsInOrder: []string{"message: \"customer name must not be empty\""}, + }, + } + + for _, c := range cases { + t.Run(c.Name, func(t *testing.T) { + multipartestutils.RunCase(t, c, pb) + }) + } +} diff --git a/docs/docsrc/examples/examples_presets/mux.go b/docs/docsrc/examples/examples_presets/mux.go index 4ec47035f..c798c0c43 100644 --- a/docs/docsrc/examples/examples_presets/mux.go +++ b/docs/docsrc/examples/examples_presets/mux.go @@ -40,6 +40,7 @@ func SamplesHandler(mux examples.Muxer) { addExample(mux, db, PresetsDetailInlineEditInspectTables) addExample(mux, db, PresetsDetailNestedMany) addExample(mux, db, PresetsDetailInlineEditFieldSections) + addExample(mux, db, PresetsDetailInlineEditValidate) addExample(mux, db, PresetsDetailSimple) return } diff --git a/presets/section.go b/presets/section.go index 2b4118cdf..e2c304561 100644 --- a/presets/section.go +++ b/presets/section.go @@ -503,8 +503,8 @@ func (b *SectionBuilder) DefaultSaveFunc(obj interface{}, id string, ctx *web.Ev } if b.validator != nil { - if vErr := b.validator(obj, ctx); vErr.HaveErrors() { - return errors.New(vErr.Error()) + if vErr := b.validator(obj, ctx); vErr.GetGlobalError() != "" { + return errors.New(vErr.GetGlobalError()) } } err = b.father.mb.editing.Saver(obj, id, ctx)