Skip to content

Ability to change go vars (both JS primitives and JS Object) after they are #Set'ed to Js.Object #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
truongsinh opened this issue Aug 14, 2014 · 15 comments

Comments

@truongsinh
Copy link

package main

import (
    "github.com/gopherjs/gopherjs/js"
)

func main() {
    var MyStringValue string

    MyStringValue = "MyStringValue1"
    js.Global.Set("MyStringValue", MyStringValue)
    println(js.Global.Get("MyStringValue")) // passed - MyStringValue1

    MyStringValue = "MyStringValue2"
    println(js.Global.Get("MyStringValue")) // passed - MyStringValue1

    MyStringPointer := &MyStringValue
    *MyStringPointer = "MyStringValue3"
    println(js.Global.Get("MyStringValue")) // failed - expected MyStringValue3, got MyStringValue1

    *MyStringPointer = "MyStringValue4"
    js.Global.Set("MyStringValue", MyStringPointer)
    println(js.Global.Get("MyStringValue")) // failed - expected MyStringValue4, got Object{}
}
@neelance
Copy link
Member

The behavior that you see is fully expected for me. In case of

var MyStringValue string
MyStringValue = "MyStringValue1"
js.Global.Set("MyStringValue", MyStringValue)
[...]
MyStringPointer := &MyStringValue
*MyStringPointer = "MyStringValue3"
println(js.Global.Get("MyStringValue"))

it is essentially the same as

var MyStringValue, GlobalMyStringValue string
MyStringValue = "MyStringValue1"
GlobalMyStringValue = MyStringValue
[...]
MyStringPointer := &MyStringValue
*MyStringPointer = "MyStringValue3"
println(GlobalMyStringValue)

and you would not expect "MyStringValue3" here, right?

In case of

*MyStringPointer = "MyStringValue4"
js.Global.Set("MyStringValue", MyStringPointer)
println(js.Global.Get("MyStringValue"))

it behaves according to http://godoc.org/github.com/gopherjs/gopherjs/js:
"Additionally, a pointer to a named type is passed to JavaScript as an object which has wrappers for the type's exported methods. This can be used to provide getter and setter methods for Go fields to JavaScript."

What do you want to achieve? Maybe I can help you to find a good solution.

@truongsinh
Copy link
Author

For example, I am researching go-angular.

package main

import (
    "fmt"
    "github.com/gopherjs/gopherjs/js"
)

func main() {
    app.NewController("MyCtrl", func(scope *ng.Scope) {
        myObject := &struct {
            MyCompany string
            MyName    string
        }{
            "company1",
            "name1",
        }
        scope.Set("myObject", myObject)
        myObject.MyCompany = "company2"
        scope.Set("myObject", myObject) // without which JS's myObject.MyCompany is still "company1"
        // scope.$apply() //?
    })
}
``

@truongsinh
Copy link
Author

In other word, one of the most significant magics of AngularJS is "two-way binding" JS <-> DOM, thus it is important for Angular-Go to have "two-way biding" from Go <- ( <--> JS <--> ) -> DOM in order to be useful.

@neelance
Copy link
Member

Maybe you can use embedded js.Objects and fields with js tags instead? I just noticed that there is no proper documentation for this feature, yet. Definitely a TODO on my list. For now, see https://github.com/gopherjs/gopherjs/blob/master/js/js_test.go#L170 With js tags, you can easily access fields of actual JavaScript objects. Pass those to AngularJS and you should have nice data binding.

@truongsinh
Copy link
Author

Yes, js tags is really potential, Thanks! However without doc, I still failed to run it. For example, with:

package main

import (
    "github.com/gopherjs/gopherjs/js"
)

type MyStruct1 struct {
    js.Object
    MyField1 string `js:"MyField1"`
}

func main() {
    myStruct1 := MyStruct1{}
    myStruct1.MyField1 = "MyField1Value2"
}

I got

panic: null is not an object (evaluating 'myStruct1.Object.MyField1 = $externalize("MyField1Value2", $String)') 

@neelance
Copy link
Member

You have to set the js.Object field, e.g. myStruct1.Object = js.Global.Get("Object").New().

@truongsinh
Copy link
Author

Thanks, it works. Is there any trick to have fields with js tag directly in Go struct, instead of being in js.Object proxy?

For example:

type MyStruct1 struct {
    o js.Object
    MyField1 string `js:"MyField1"`
}

MyStruct1. MyField1 in Go is translated into MyStruct1. MyField1 in JS instead of MyStruct1.o. MyField1

@neelance
Copy link
Member

Only the type js.Object can encapsulate native JavaScript objects. Do you ask because of nested objects?

@truongsinh
Copy link
Author

Yes, nested object is lengthy, like MyStruct1.o. MyField1.o.MyField2, and it does not play well with AngularJS $scope

@neelance
Copy link
Member

I'll try to come up with some better solution.

@truongsinh
Copy link
Author

(y)

@truongsinh
Copy link
Author

Have you had anything lead on this issue yet?

@neelance
Copy link
Member

I haven't forgotten this issue. I just have many things to do atm, sorry. I will take care of this at some point! :-)

@myitcv
Copy link
Member

myitcv commented Apr 26, 2017

I think this discussion is superseded by the proposals in #633 and #634

@shurcooL - we can probably close this (it's also quite an old issue)

@truongsinh please shout if you feel like #633 and #634 don't address your issue.

Thanks

@nevkontakte
Copy link
Member

After reading the discussion in this issue, I tend to agree with #79 (comment). The original example seems to be working as intended and #236 appears to cover the literal initialization issue discussed later in the thread.

I am going to close this issue now, but if you think this is a mistake — please let me know and we can reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants