wails icon indicating copy to clipboard operation
wails copied to clipboard

binding / typescriptify: nested structs are not "known"

Open devnode opened this issue 2 years ago • 1 comments

Description

https://github.com/wailsapp/wails/blob/43f8a1f773f3a3ce03898da65335abca62f898a5/v2/internal/binding/reflect.go#L101-L108

https://github.com/wailsapp/wails/blob/43f8a1f773f3a3ce03898da65335abca62f898a5/v2/internal/typescriptify/typescriptify.go#L631-L634

since there's no recursion when a binding a struct, a nested struct will not be added to typescriptify.KnownStructs, which leads to an invalid modules.ts file being generated and eventually a console error of: Uncaught TypeError: n is not a constructor.

// one line workaround
func (a *App) StructSettings() Settings { return Settings{} }

To Reproduce

app.go

type Config struct {
    Target string `json:"target"
    Settings Settings `json:"settings"`
}

type Settings struct {
    Enabled bool `json:"enabled"`
}

...

func (a *App) ConfigState() Config {
    ...
    return a.cfg
}

frontend/wailsjs/go/models.ts

export namespace main {
    export class Config {
            // Go type: Settings
            settings: any;  
            ...
	    constructor(source: any = {}) {
	        if ('string' === typeof source) source = JSON.parse(source);
	        this.target = source["target"];
	        this.settings = this.convertValues(source["settings"], null);
	    }
            ...
    }

    // this generated fine
    export class Settings {
    ...
    }
}

Expected behaviour

frontend/wailsjs/go/models.ts

export namespace main {
    export class Config {
            settings: Settings;  
            ...
	    constructor(source: any = {}) {
	        if ('string' === typeof source) source = JSON.parse(source);
	        this.target = source["target"];
	        this.settings = this.convertValues(source["settings"], Settings);
	    }
            ...
    }
    ...
}

Screenshots

No response

Attempted Fixes

main.go

	err := wails.Run(&options.App{
                ...
		Bind: []interface{}{
			app,
			&Config{},
			&Settings{},
		},
	})

System Details

System
------
OS:		Fedora Linux
Version: 	36
ID:		fedora
Go Version:	go1.18.3
Platform:	linux
Architecture:	amd64

Wails
------
Version: 		v2.0.0-beta.37
Package Manager: 	dnf

Dependency	Package Name		Status		Version
----------	------------		------		-------
*docker		Unknown			Not Found	
gcc		gcc-c++			Installed	12.1.1
libgtk-3	gtk3-devel		Installed	3.24.34
libwebkit	webkit2gtk3-devel	Installed	2.36.3
npm		npm			Installed	8.3.1
pkg-config	pkgconf-pkg-config	Installed	1.8.0

Additional context

as for a solution, i'm a bit rusty on reflection but maybe we can just add another field to options.App:

	err := wails.Run(&options.App{
                ...
		Models: []interface{}{
			Settings{},
		},
	})

this way, we can just have the models generated without generating bindings for all the "useless" functions as well.

devnode avatar Jun 21 '22 20:06 devnode

Can you please test this with the latest release? A fix went in for a similar scenario. If it does not work, could you please add a test to this file 🙏

leaanthony avatar Aug 20 '22 05:08 leaanthony

Please try the above PR to see if this fixes your problem. If you are unsure how to do this, please follow this guide. Let us know how you get on 👍

leaanthony avatar Sep 26 '22 08:09 leaanthony

The PR has now been merged. If this issue is still valid, please reopen. Thanks 👍

leaanthony avatar Oct 01 '22 05:10 leaanthony