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

Support Component static method #480

Closed
dinoboff opened this issue Apr 13, 2017 · 6 comments
Closed

Support Component static method #480

dinoboff opened this issue Apr 13, 2017 · 6 comments

Comments

@dinoboff
Copy link

dinoboff commented Apr 13, 2017

Static methods could be used to define alternative constructors. For example, a rich text editor component could define a from static method initialising the component data from an existing textarea:

export default {
  data() {
    value: ''
  },
  
  // The component constructor need to be provided to those methods.
  staticMethods(Component) {
    
    // Return a dict of static methods
    // (or attach them directly)
    return {
      from(textarea) {
        const value = textarea.value;
        const parent = textarea.parentNode;
        const target = document.createAttribute('span');
        
        textarea.style.display = 'none';
        parent.insertBefore(target, textarea);

        const editor = new Component({target, data: {value}});
        const sub = editor.on('destroy', function() {
          textarea.style.display = 'initial';
          textarea.value = this.value;
          parent.removeChild(target);
          sub.cancel();
        });

        return editor;
      }
    };
  }
};

It's easy enough to define those methods in an other module, but having those kind of methods defined with the component would be tidier.

@Conduitry
Copy link
Member

Conduitry commented Apr 13, 2017

This would be pretty simple to implement in a naive way - we could just keep that staticMethods method in the template object, and then just generate code to call

assign( component, template.staticMethods( component ) );

but I'm wondering whether there's some more static analysis we ought to be doing if we implemented this.

@Rich-Harris
Copy link
Member

Can definitely see the value in being able to declare static methods (and properties). Can also see why it makes sense to implement as a function, since new this(...) feels like a weird thing to write.

Given that, what if it's a more general purpose setup hook, like this?

export default {
  data() {
    value: ''
  },
  
  // The component constructor need to be provided to those methods.
  setup (Component) {
    console.log( 'adding some static methods and properties' );

    Component.from = function ( textarea ) {
      // ...
    };

    Component.SOME_CONSTANT = 42;
  }
};

In other words, Svelte makes no assumptions about whether the setup work involves declaring static methods, or overriding built-in methods for some esoteric debugging purposes or whatever — it's just a convenient place to do that work.

setup might not be the best name for it though... open to suggestions.

It does move us away from a world where the compiler can know almost everything about the component and how it can be used, into one where the behaviour becomes a black box. But as you point out, someone could do that anyway since it's just a regular JS constructor, they'd just be doing it in an even less predictable (to the compiler) way.

@orlov-vo
Copy link

@Rich-Harris what about static methods and properties in v3?

@pngwn
Copy link
Member

pngwn commented Jul 26, 2019

You can do this in v3 by using the context="module" script.

<script context="module">
  export const toUpper = str => str.toUpperCase();
</script>

This function can then be imported and used from anywhere:

import { toUpper } from './Component.svelte';

const myStr = toUpper('hi');

See the context="module" documentation or the Sharing Code section of the tutorial for more information.

@orlov-vo
Copy link

@pngwn Thanks! But your reply about named export, not about static methods or properties. It is different things. For example static methods/properties are more convenient in some cases, when you need more coherence between a class and meta-data when this bunch traveling through a program.

For example:

<script>
  export let Item;
</script>

{#if Item.TYPE === 1}
  <svelte:component this={Item} foo bar={32} />
{:else}
  <div class="wrapper">
    <svelte:component this={Item} />
  </div>
{/if}

Yes, I can pass a object with TYPE and Item, but it is hack. Isn't it?

<script>
  export let obj;
</script>

{#if obj.TYPE === 1}
  <svelte:component this={obj.Item} foo bar={32} />
{:else}
  <div class="wrapper">
    <svelte:component this={obj.Item} />
  </div>
{/if}

@pngwn
Copy link
Member

pngwn commented Jul 26, 2019

Come to one of the support channels (Stack Overflow or Discord Chat) and we can help you with this. Github isn't the place for support questions.

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

5 participants