Skip to content
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

How to access a viewModel instance? #10

Closed
marshallswain opened this issue Nov 13, 2016 · 3 comments
Closed

How to access a viewModel instance? #10

marshallswain opened this issue Nov 13, 2016 · 3 comments

Comments

@marshallswain
Copy link
Contributor

marshallswain commented Nov 13, 2016

In the following example, I create a ViewModel and connect it to an imported AppHome component.

import AppHome from './app.jsx';

export const ViewModel = DefineMap.extend({
  message: {
    type: 'string',
    value: 'Hello, Feathers!'
  },

  changeMessage () {
    this.message = 'Hello, Marshall!';
  }
});

const AppContainer = connect(ViewModel, AppHome);

Suppose I want to pass message in the example to a component several levels deep. I'm passing the ViewModel constructor to the connect function, but how do I export the actual viewModel instance to make it available elsewhere? This is needed to link up can-route to a viewModel:

var ViewModel = DefineMap.extend({
    petType: "string",
    storeId: "number"
});

var viewModel = new ViewModel({
    petType: "string",
    storeId: "number"
});

route.data = viewModel;

Is there a way to extract the viewModel once its component has been rendered to the DOM?

@marshallswain
Copy link
Contributor Author

Being able to pass a viewModel instance to the connect function is probably the best solution to this, but we probably will have to fix enumerability of DefineMap instance props.

Extracting from the DOM would only be a somewhat less messy solution for the top level component. For components that aren't calling ReactDOM.render themselves, it would be nothing but messy.

@BigAB
Copy link
Owner

BigAB commented Nov 16, 2016

I think you just need to rethink what you are doing here.

You almost certainly don't want get the viewModel off the DOM, this is React, the DOM has been extracted away.

If you needed access to the viewModel from an parent component you could use a ref to get the component and then access it at component.viewModel.

But for your use case, what you want to do is but the message, outside of the component viewmodel, in it's own state (or pass it through components all the way down).

import AppHome from './app.jsx';
import compute from 'can-compute';

export const message = compute('Hello, Feathers!');

export const ViewModel = DefineMap.extend({
  get message() {
     return message();
  },
  changeMessage () {
    message('Hello, Marshall!')
  }
});

const AppContainer = connect(ViewModel, AppHome);

...now you could export message from the AppContainer:

import { message } from '/components/AppContainer';

...or more likely you would have some model or something seperate that had message in it, that you would export and pass around.

RE: routing
As discussed on a call, the best way to connect a router is to use the router.data as a property on the viewmodel, or use derived values from the router.data as appropriate.

Let me know if you want to discuss more or if this issue can be closed.

@marshallswain
Copy link
Contributor Author

marshallswain commented Nov 16, 2016

Very nice. Yeah, I figured out the routing demo after I posted this, which works wonderfully. Between that and the examples you've posted, there's just enough flexibility to do pretty much anything👏🎉

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

2 participants