I am not able to pile my svelte ponent when using a get/set pair in custom methods. Is this not supported? Or am I doing something wrong?
Example:
Say I wanted to have a ponent that displays a name and I want to set the name using.
.name = 'The new name';
However I only want the ponent to use the name if it has no spaces in the name.
<h1>Hello {{name}}!</h1>
<script>
export default {
data () {
return {
name: 'The Name',
}
},
methods: {
get displayName() {
return this.get('name');
},
set displayName(val) {
if (val.indexOf(' ') < 0) {
this.set('name', val);
}
}
}
}
</script>
The Issue is that when I try to pile this, it says there is a duplicate key.
Duplicate property 'displayName'
49: return this.get('name');
50: },
51: set displayName(val) {
Here is a REPL - /repl?version=1.13.2&gist=0eeab5717526694139ba73eae766bb30
I don't see anything in the documentation about this. I can just not use setters, but I would like to be able to.
I am not able to pile my svelte ponent when using a get/set pair in custom methods. Is this not supported? Or am I doing something wrong?
Example:
Say I wanted to have a ponent that displays a name and I want to set the name using.
.name = 'The new name';
However I only want the ponent to use the name if it has no spaces in the name.
<h1>Hello {{name}}!</h1>
<script>
export default {
data () {
return {
name: 'The Name',
}
},
methods: {
get displayName() {
return this.get('name');
},
set displayName(val) {
if (val.indexOf(' ') < 0) {
this.set('name', val);
}
}
}
}
</script>
The Issue is that when I try to pile this, it says there is a duplicate key.
Duplicate property 'displayName'
49: return this.get('name');
50: },
51: set displayName(val) {
Here is a REPL - https://svelte.technology/repl?version=1.13.2&gist=0eeab5717526694139ba73eae766bb30
I don't see anything in the documentation about this. I can just not use setters, but I would like to be able to.
Share Improve this question edited Mar 29, 2017 at 18:35 Zac asked Mar 29, 2017 at 18:20 ZacZac 2,21124 silver badges49 bronze badges2 Answers
Reset to default 7tl;dr this is possible with a wrapper object
The error message here is a bit confusing — it's not the duplicate property that's a problem, is that you can't have getters and setters in methods
, which in any case is separate from the data
object that populates a ponent's internal state (along with data supplied at instantiation and any puted values there might be). I've opened an issue for that here.
The data
itself also can't have getters and setters — or rather it can, but they won't be used, because the object returned from your data
function isn't the same as the internal state object (otherwise we'd all probably run into mutation-related bugs).
But it's actually fairly easy to create a wrapper object that allows you to get and set a ponent's data:
function wrap (ponent) {
var wrapper = {};
var data = ponent.get();
Object.keys(data).forEach(key => {
Object.defineProperty(wrapper, key, {
get() {
return ponent.get()[key];
},
set(value) {
ponent.set({ obj[key]: value });
}
})
});
return wrapper;
}
var ponent = new Component({...});
var wrapper = wrap(ponent);
wrapper.name = 'Rich';
You could even do ponent.data = wrap(ponent)
if you were so inclined — then you could manipulate ponent.data.name
and so on.
I've put together a small repo demoing that approach — see it in action here.
Edit: As Rich Harris pointed out in the ments below, getters and setters won't work within data
because Svelte copies the properties to a plain JS object internally (thus ignoring getters and setters). I think the next best thing you can do is make a method name
that can be called like name()
as a getter, and name(value)
as a setter.
Svelte Code:
<h1>Hello {{_name}}!</h1>
<script>
export default {
data() {
return {
_name: 'The Name'
}
},
methods: {
name(value) {
if (value === void 0) return this.get('_name')
this.set('_name', value)
}
}
}
</script>
Original Post:
Your getter and setter should be in your data
rather than your methods
, because they create a property in the end. This property conflicts with the name
you defined as equal to 'The Name'
inside your original data
method. I would suggest using a "private" property _name
instead.
Svelte Code (REPL):
<h1>Hello {{name}}!</h1>
<script>
export default {
data() {
return {
_name: 'The Name',
get name() {
return this._name
},
set name(value) {
/ /.test(this._name) || (this._name = value)
}
}
}
}
</script>