Set title of view dynamically [object object]


#1

Hi guys, this is my first post, and my first nativescript application. I’m guessing this is a trivial problem, and I’m missing something since I have been trying to fix it for over an hour.

I’m creating a simple drawe app, the user get’s a radlistview with customers (working), when they click on one of the customers they see a list of products that the customer ordered (working.)

The way I set it up:

in home-page.js I have an Observable array, I make an ajax request and fill the observable array with a list of customers, which gets added to the HomeViewModel and the view displays the radlistview perfectly.

Now when the user clicks on a customer, I navigate to details-page.js, the press handler in home-page.js looks like this:`exports.pressHandler= function(e){

 var navigationOptions={
    moduleName:'details/details-page',
    context:{
            orderDetails: e.object.getSelectedItems()
            }
};
frameModule.topmost().navigate(navigationOptions);

}`

the orderDetails variable contains the pressed object which looks a bit like:
{
customerCode: '12345’
customername: ‘John Doe’,
products: [{productobject}, {productobject]
}

the details-page.js file, gets the products and adds it to a radlistview (this works) :


const frameModule = require("ui/frame");
var ObservableArray = require("data/observable-array").ObservableArray;
var Observable = require("data/observable").Observable;
const DetailsViewModel = require("./details-view-model");

var DetailsView = new DetailsViewModel();

var page;
var items = new ObservableArray([]);
var customerData = new Observable({});
/* ***********************************************************
* Use the "onNavigatingTo" handler to initialize the page binding context.
*************************************************************/

function onNavigatingTo(args) {
    /* ***********************************************************
    * The "onNavigatingTo" event handler lets you detect if the user navigated with a back button.
    * Skipping the re-initialization on back navigation means the user will see the
    * page in the same data state that he left it in before navigating.
    *************************************************************/
    if (args.isBackNavigation) {
        return;
    }
    
    const page = args.object;
   
    if(page.navigationContext) {

         while(items.length>0){
        items.pop();
    }
    items.push(page.navigationContext.orderDetails[0].products);
    customerData.customerName = "Test";
    }  
    
}


exports.loaded = function(args) {
    page = args.object;
    DetailsView.set("orderProducts", items);
    DetailsView.set("customerData",  {customerName : 'Test'});
    page.bindingContext = DetailsView;
}

the thing that isn’t working is customerData, I replaced the real customerData with customerData.customerName = “test”; to see if this would work, but in the view when I set the title to be:

I only see [object object].

the homeviewmodel looks like this:

const observableModule = require("data/observable");

function DetailsViewModel() {


    const viewModel = observableModule.fromObject({
    	
    });

    return viewModel;
}

module.exports = DetailsViewModel;

however when I put the customerData inside the homeviewmodel, I do see “test” in the view title :

const observableModule = require("data/observable");

function DetailsViewModel() {


    const viewModel = observableModule.fromObject({
    	customerData: {customerName: 'TEST'},
    });

    return viewModel;
}

module.exports = DetailsViewModel;

Can anyone tell me how I will be able to add the customerData from the controller, and not the viewmodel?

EDIT:
I got it to work, but still would like to know what the difference is, when I change in details-page.js:

    exports.loaded = function(args) {
        page = args.object;
        DetailsView.set("orderProducts", items);
        DetailsView.set("customerData",  {customerName : 'Test'});
        page.bindingContext = DetailsView;
    }

TO:

    exports.loaded = function(args) {
        page = args.object;
        DetailsView.set("orderProducts", items);
        DetailsView.customerData =  customerData;
        page.bindingContext = DetailsView;
    }

it works, I also change the var customerData from Observable() to {} (normal object)

Now I can access the object variables from within the view without getting [object object], but I can’t set orderProducts for the radlistview in the same way, that var needs to be added with detailsview.set for it to work, I just don’t know why?


#2

Hi @thomasl,

The set() method is basically a trigger for NativeScript to update all the things. Without the trigger NativeScript doesn’t know your view model changed.

So suppose you have a basic Observable object.

const Observable = require("data/observable").Observable;
var viewModel = Observable.fromObject({ appTitle: "My App" });

And then you bind to that view model in your UI.

<ActionBar title="{{ appTitle }}"></ActionBar>

If you change the appTitle property directly, for example viewModel.appTitle = "New Title", NativeScript has no way of knowing that the property changed, and therefore will not update the <ActionBar>. (NativeScript doesn’t do any poll-based watching of JavaScript objects, which is how AngularJS works.)

Instead you need to do viewModel.set("appTitle", "New Title"), which informs NativeScript that the view model changed, and gives NativeScript the chance to trigger event handlers and repaint the user interface as necessary.

Does this make sense? If you have any specific areas of the documentation or the tutorials you think could use this level of detail let me know.


#3

Thanks for your reply, it makes sense, but in my view where I use these variables:

the variables I’m using in that view:

<Label height="25" text="{{customerData.customerName}}" class="customerInfo"></Label>
<Label height="25" text="{{customerData.customerAddress}}" class="customerInfo"></Label>
<Label height="25" text="{{customerData.customerCity}}" class="customerInfo"></Label>

why is it when I use this:
DetailsView.customerData = customerData;

It will display my view correctly, but when I use this:

DetailsView.set("customerData", customerData);

on the same view it will display [object object] where normally the name, address would be.

EDIT:
It seems like I forgot to add the variable customerData to the viewmodel observable, after adding it there as well it worked. thanks for your explanation.


#4

Yeah no worries, and glad you got this figured out!