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

Already on GitHub? Sign in to your account

toJSON issue #128

Open
imrefazekas opened this Issue Jul 11, 2013 · 11 comments

Comments

Projects
None yet
3 participants
Contributor

imrefazekas commented Jul 11, 2013

Dear finnsson,

I got an issue while calling toJSON.

console.log( ko.toJSON( theViewModel ) );

pager.extendWithPage( theViewModel );

console.log( ko.toJSON( theViewModel ) );

The first executed perfectly

{"personal":{"sex":"male", ....

the second console logging fails:

TypeError: JSON.stringify cannot serialize cyclic structures.

How can I use the toJSON of knockout? What do I miss?

Thanks,

Imre

Owner

finnsson commented Jul 11, 2013

I've actually never tried to call ko.toJSON. The error is due to that a page keeps a reference to its parent page while the parent-page keeps a reference to its children (thus cyclic structures). I don't know if there is some way I can instruct ko.toJSON to skip some of these fields. I read at Controlling how an object is converted to JSON that I should probably implement pager.Page.prototype.toJSON. I haven't tried anything but a solution might be

pager.Page.prototype.toJSON = function() {
    return this.ctx;
};
Contributor

imrefazekas commented Jul 11, 2013

Wrote a simple test:

<!DOCTYPE html>
<html>
  <head>
    <script src="/js/lib/jquery-2.0.3.min.js"></script>
    <script src="/js/lib/knockout-latest.js"></script>
    <script src="/js/lib/pager.min.js"></script>
  </head>
  <body>
  <script type="text/javascript">
        function AppViewModel() {
            this.firstName = ko.observable("Bert");
            this.lastName = ko.observable("Bertington");

            this.fullName = ko.computed(function() {
                return this.firstName() + " " + this.lastName();
            }, this);

            this.capitalizeLastName = function() {
                var currentVal = this.lastName();   // Read the current value
                this.lastName(currentVal.toUpperCase()); // Write back a modified value
            };
        }

        var theViewModel = new AppViewModel();

        console.log( ko.toJSON( theViewModel ) );

        pager.extendWithPage( theViewModel );

        console.log( ko.toJSON( theViewModel ) );

        ko.applyBindings(new AppViewModel());
    </script>
  </body>
</html>
Owner

finnsson commented Jul 11, 2013

Jepp. It works in that case. I would recommend that you just add

pager.Page.prototype.toJSON = function() {
    return this.ctx;
};

for now. I'll try to add and test it for the 1.1-release.

Contributor

imrefazekas commented Jul 11, 2013

OK, thank you.

Contributor

imrefazekas commented Jul 11, 2013

After executing this:

ko.applyBindings(theViewModel);

I receive this Error for toJSON:

Pass a function that returns the value of the ko.computed
Contributor

imrefazekas commented Jul 11, 2013

By executing this:

    theViewModel.toJSON = function() {
        var copy = ko.toJS(this);
        delete copy['$__page__'];
        return copy;
    };

The JSON export seems fine till the applyBindings. After it I receive that message.
If I put the pager usage into comments, everything is fine.

Contributor

imrefazekas commented Jul 11, 2013

Here is a complete very small sample what I'm dealing with, hope it helps:

<!DOCTYPE html>
<html>
<head>
    <script src="/js/lib/jquery-2.0.3.min.js"></script>
    <script src="/js/lib/knockout-latest.js"></script>
    <script src="/js/lib/pager.min.js"></script>
</head>
<body>
    <div data-bind="page: {id: 'ignite', title: 'Greetings', role: 'start'}">
        Sportif: <input type="checkbox" data-bind="checked: personal.sportif" />
    </div>
    <script type="text/javascript">
        $(document).ready(function(){
            pager.Page.prototype.toJSON = function() {
                return this.ctx;
            };
            function AppViewModel() {
                this.firstName = ko.observable("Bert");
                this.lastName = ko.observable("Bertington");

                this.fullName = ko.computed(function() {
                    return this.firstName() + " " + this.lastName();
                }, this);

                this.capitalizeLastName = function() {
                    var currentVal = this.lastName();   // Read the current value
                    this.lastName(currentVal.toUpperCase()); // Write back a modified value
                };

                this.personal = {
                    sportif: ko.observable( false )
                };
            }

            var theViewModel = new AppViewModel();

            console.log( '?', ko.toJSON( theViewModel ) );

            pager.extendWithPage( theViewModel );

            console.log( ':', ko.toJSON( theViewModel ) );

            ko.applyBindings( theViewModel );

            console.log( '-', ko.toJSON( theViewModel ) );

            pager.start();

            console.log( '*', ko.toJSON( theViewModel ) );
        });
    </script>
</body>
</html>

And a jsfiddle: http://jsfiddle.net/ndJsk/

Is there anything I can help?

Contributor

imrefazekas commented Jul 12, 2013

The problem is, that after the pager starts, some elements will posses attributes like this:

selectionDirection: [Exception: Error]
selectionEnd: [Exception: Error]
selectionStart: [Exception: Error]

And here the knockoutJS will fail to generate the JS object so the JSON also.
Without the pager, the input field in the test html won't have such exceptions.

Contributor

imrefazekas commented Jul 12, 2013

Commenting out all pager-related code from temp.html and the input element does not have such attributes and knockout runs perfectly.

Contributor

imrefazekas commented Jul 12, 2013

Just made a workaround solution: #130
Maybe not the best solution but works perfectly for me.

mw44118 commented Jun 19, 2015

Any chance that fix can get merged in and released? I love using ko.toJSON to watch stuff change, and it doesn't work with pager!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment