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

Implement <svelte:target> special component. #1321

Closed
hperrin opened this issue Apr 5, 2018 · 7 comments
Closed

Implement <svelte:target> special component. #1321

hperrin opened this issue Apr 5, 2018 · 7 comments

Comments

@hperrin
Copy link
Contributor

hperrin commented Apr 5, 2018

Having a <svelte:target> special component that references the component's target element would be really useful instead of having to use addEventListener on this.options.target.

Basically, turn this:

{#if show}
  <span class="tooltip">{text}</span>
{/if}

<script>
  export default {
    oncreate() {
      this.set({'mouseover': () => { this.set({'show': true}); }});
      this.set({'mouseout': () => { this.set({'show': false}); }});
      this.options.target.addEventListener('mouseover', this.get('mouseover'));
      this.options.target.addEventListener('mouseout', this.get('mouseout'));
    },
    ondestroy() {
      this.options.target.removeEventListener('mouseover', this.get('mouseover'));
      this.options.target.removeEventListener('mouseout', this.get('mouseout'));
    },
  };
</script>

Into this:

<svelte:target on:mouseover="set({'show': true})" on:mouseout="set({'show': false})">
  {#if show}
    <span class="tooltip">{text}</span>
  {/if}
</svelte:target>

Or maybe this:

<svelte:target on:mouseover="set({'show': true})" on:mouseout="set({'show': false})" />
{#if show}
  <span class="tooltip">{text}</span>
{/if}

And make it a lot easier to do things like this:

<svelte:target href="/app/{ section }/{ entity }" />
const link = new Link({
  target: domAnchorElement,
  data: {
    section: domAnchorElement.dataset.section,
    entity: domAnchorElement.dataset.entity
  }
});

Edit: Updated for v2.

@hperrin
Copy link
Contributor Author

hperrin commented Apr 5, 2018

@ansarizafar
Copy link

I like this idea.

@hperrin
Copy link
Contributor Author

hperrin commented Apr 6, 2018

I was thinking, in order to make this easily integrate into existing components, we can prevent the user from putting markup inside it, like the <:Window> tag. That way the <:Target> tag can just be plopped on top of an existing component:

<:Target on:mouseover="set({'show': true})" on:mouseout="set({'show': false})" />
{{#if show}}
  <span class="tooltip">{{text}}</span>
{{/if}}

@hperrin hperrin changed the title Implement <:Target> special component. Implement <svelte:target> special component. Apr 19, 2018
hperrin added a commit to hperrin/svelte that referenced this issue Apr 20, 2018
@arxpoetica
Copy link
Member

I see where you're headed with this, but something about it feels like the wrong approach. Haven't been able to put my finger on it yet. Are there any viable alternatives? I think it might be the case that allowing code to "target" something parent that easily would lend itself too easily to spaghetti code, but then again that's sort of what bindings do. </svelte:scratches-head>

@hperrin
Copy link
Contributor Author

hperrin commented Apr 20, 2018

If there's another way to have two components operate on the same element, that could work. What I'm thinking is, without intentional spaghetti code, there isn't a way to have a component for styling and a component for routing, for example, both operate on an a element. And it just seems wrong to have a component for doing both, but that's the current state of Svelte applications.

Edit: At least, that's the currently possible way to do it Svelte-ily. You can, of course just have a Svelte component to provide the scaffolding around DOM manipulation.

@arxpoetica
Copy link
Member

arxpoetica commented Apr 26, 2018

I'm not officially for or against this—I can see the utility—but it does still seem like a rabbit hole to me. It goes against the grain of self contained components and wouldn't work well with a component marketplace...you'd have to specify that component a only works with component b.

Another question: wasn't this what decorators were included for? Or is that orthogonal.

I dunno. Your particular use case makes sense. I'm just wondering aloud (for the sake of thinking through it) whether components need to be loosely or more tightly coupled.

One problem that actually goes beyond the scope of this solution is that in plain vanilla applications, DOM interacts with DOM all over the place. So maybe we ought to expand the scope of your particular use case.

Examples:

  • open menu somewhere? Clicking on the body should close it. (Very common need.) Similar: popups, etc.
  • drag and drop elements to completely different sections of layout
  • your tooltip hover needs
  • dropdown menus where the hover container is outside the scope of the child dropdown component
  • multitouch or multistate interactions where users have to touch on a phone/tablet in multiple spots for behavior
  • etc

So here's my broader question. How does one, in a sveltish way, span the interactive DOM gap (without decorators?) and without spaghetti code? (Or is decorators THE answer?)

In theory, app-level Store variables and observers answer this, but maybe there needs to be a bigger idea here.

In sum, this is a common problem I've encountered in these types of frameworks (Ractive had the problem) and I have yet to hear a really satisfying solution.

@Rich-Harris
Copy link
Member

I'm going to close this for the reasons in #1355 (comment), and because I haven't heard this feature request other than in this issue

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

4 participants