router.push fails

Hi fusers!

router.push in the following code gives the error: System.Exception: Route cannot be null
I was confused because I was using the exact same call in another module which works fine. And more confused because converting it to a json string and back to a js object works! I.e. changing router.push(“detailView”, args.data); to router.push(“detailView”, arg2.data); works.
(btw, the strings output by the two console.logs are identical).

gotoDetailView: function (args) {
    var arg2=JSON.parse(JSON.stringify(args));
    console.log("args1: " + JSON.stringify(args));
    console.log("args2: " + JSON.stringify(arg2));
    router.push("detailView", args.data);
}

Hi Paul,

we’ll need to see more of your code; a complete, minimal reproduction would be nice.

The Route cannot be null error can only be thrown from this place in code, so it might not be happening where you think it is.

Thanks Uldis,

It’s probably something I’m doing wrong, it’s my first app.

I’ve attached the complete project (there’s not much too it) as I’m having a number of problems:

  1. the one mentioned in this post
  2. blocking loading indicator, mentioned another.
  3. clicking on an item in scrollview goes to detail view and pressing the back arrow returns as expected. But if the item is double clicked GoBack in the detail page does nothing.

I know you’re a busy man and with thousands of users requiring assistance I’ll understand if you can’t but I don’t know enough yet to resolve these problems, would appreciate your help!

It’s best if separate issues are handled in separate forum threads.

Having taken a look at the code of yours, I suspect the root cause of the issue is in how you’re passing around the model as a property. I didn’t get to debugging the exact behaviour, but the approach itself is wrong (from the perspective of how things should be done in Fuse). I can imagine that the router instance somehow gets confused to what Observables it needs to refer to when new instances of other pages are spawned, and arbitrary [copies of] objects get injected into those.

When you have, or want to have a shared global state, that state should be kept in a stand-alone JS model. I understand that’s what you’ve tried to implement, but in Fuse, it’s done slightly differently. For a good explanation on what the correct approach would be, please see this post and follow the links for details.

Hope this helps!

It does help! I recently changed it to pass the model name as a property rather than the model itself. Will study the links too. It’s all learning. Thanks for your patience.

Hey Uldis, I experimented with this a little and realized it is the same problem reported in this post:

https://www.fusetools.com/community/forums/howto_discussions/callback_with_arguments?page=1

What was the result of the slack discussion coz I think it will solve what I want to do.

Specifically when using Each to iterate over items and passing the data context to a subpage using router.push(“page_name”, args.data), you get a router cannot be null when the data context is an object like {a:1, b:1} and you do not specify the property. I.e. passing args.data gives the error but passing args.data.a does not.

In my case I have an object containing meta data with a nested object containing the actual data of the form {id: 1, changed: true, data: {name: “Paul”, address: "555 Main Street, …}}

I want to pass the whole object to router.push rather than passing individual properties. I can pass args.data.id, args.data.changed, args.data.data without error but not args.data unless I json.parse(json.stringify(args.data)) first.

Also I can successfully pass the entire object when not using Each, i.e. the following works (I guess because I can reference the object by name (spData)):

    var spData = {id : "1", nestedData:{a:2, b:3}}
    module.exports = {
        spData: spData,
        gotoSimplePage: function (args) {router.push("simplePage", args.data.spData)}
    }

The problem is likely not where you think it is. Router happily accepts [almost] any complex objects you throw at it in a goto or push.

The one thing that you’re likely missing is that you can only pass serialisable objects. This means that the objects you pass may not hold functions or other things that cannot be serialised. Perhaps in your Each you’re iterating over a collection of objects that have functions attached to them, or maybe they hold Observables (which have functions attached to them implicitly).

There is absolutely nothing holding you back from constructing a new, simple object right before you pass it to router either:

function gotoSimplePage(args) {
    var obj = {a: args.data.a, b: args.data.b};
    router.push("simplePage", obj);
}

Which brings me to a point: always post complete reproductions of your code, otherwise it’s impossible to help.

Don’t want to be a pain but I already sent you the complete project in the zip file. After you original response changed it to not pass the model around but it still has the same problem. But what you said has helped - the object does contain observables. So I guess json.stringify is making it serializable even though it is not from a fuse perspective. Obviously I am a beginner with fuse and just trying to understand things. No big deal though, I can just use any of the work-arounds above. I just wanted to pass the entire object to make things as generic as possible.

Yes, and the complete project is way too big to count as a minimal reproduction :slight_smile:

Nothing wrong about being a beginner. We all started somewhere!

What JSON.stringify() does, is it creates a string. That is not exactly what you should be passing either, because then you can’t directly access the children of that object (string is a string after all).

It was suggested before, and I’ll repeat: you should only be passing a unique reference to the object (like an ID), and keep the data in a model, which you can require() from both the calling page, and the receiving one. In this case, a single source of truth is better than juggling copies of objects. This was recently explained in another forum thread.

Yes thanks Uldis, that’s it, the embedded observables in the data structure. How do I correctly do this then, create a new simple object like you suggested, without the observables?

See my reply above :slight_smile: Only pass around an ID, keep the data in a model.

I posted before I read your answer. Clear now thanks.