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

If $element is on a ViewModel, add the component's element to the viewModel #295

Open
justinbmeyer opened this issue Aug 24, 2018 · 4 comments

Comments

@justinbmeyer
Copy link
Contributor

If I have a component with $element as part of its definition as follows:

Component.extend({
  ViewModel: {
    $element: "any",
    width: {
      value({listenTo, resolve}){
        listenTo("$element",(ev, element)=>{ resolve(element.clientWidth) })
      }
    }
  }
});

I would like Component to automatically assign it's element to that ViewModel.

@justinbmeyer
Copy link
Contributor Author

As a side proposal, I think it would be very cool to make the following work:

Component.extend({
  ViewModel: {
    $element: "any",
    get width(){
      return this.$element && this.$element.clientWidth
    }
  }
});

One way to do this would be to overwrite a LOT of the DOM's properties so they call ObservationRecorder.add(). I'm not sure the DOM can be overwritten in this way. Another alternative might be to add can.getKeyValue to symbols so the following would at least work:

Component.extend({
  ViewModel: {
    $element: "any",
    get width(){
      return get(this, "$element.clientWidth");
    }
  }
});

(where get is using canReflect.getKeyValue() under the hood).

@mjstahl
Copy link

mjstahl commented Aug 24, 2018

My gut tells me this is a bad idea due to violating "the separation of concerns".

I understand there are times when getting direct access to a part of the DOM from VM is necessary, but it should be difficult and we should not encourage the practice.

And by "not encourage", I mean we should just say to people,

Use the DOM APIs if you want to infect your VM with DOM code.

@justinbmeyer
Copy link
Contributor Author

justinbmeyer commented Aug 24, 2018

To be clear, this isn't a "necessary evil". This is the RIGHT thing to do in many cases such as the one I talked about in Bitballs. We should encourage it.

We should encourage it when the DOM needs to be a source of state. This is common for things like an element's width, its scroll position, etc.

It should be discouraged when writing to the DOM, which should be done via stache or within the connected callback.

Finally, in the can-element future of CanJS, there is no distinction between viewModel and element. They are one and the same. This makes sense because the element can have state that needs to be managed.

Finally pt 2, I would like to see some "bad" examples where this gets abused, or somehow this creates worse code than what would have existed without it. Putting it another way, I am very skeptical this is going to lead to worse code than what exists now.

@CODE-REaD
Copy link

First, I confess I'm not clear on the proposal. Justin, I would be helped if you would illustrate your statement I would like Component to automatically assign it's element to that ViewModel with an example. IOW, why expose $element in this way?

(It would also help me if you didn't use the word element four times in your example; please try to use at least two different words).

Second, I find this conversation compelling as it involves the problem of hierarchy (i.e., what can be accessed from where) that I seem to keep hitting with CanJS. The more the boundaries can be clarified and explained the better off I (and I suspect others) will be.

Thanks to all.

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

No branches or pull requests

4 participants