en en en en en en en en en en en en en en en en en en fa en en fr hbs_lat en en en es en en en ms en de en fr en en en ca en en en en en en en en ms en en en en en en en en en en en en en en en en en en en en en es en en en en en en en en vi en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en vi en en en en en en en en en en en en es en en en en en en en en en en en en en en en es en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en es en en nl en en zh en en sv en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en ru en en en en en en en en en en en en en en en en ru en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en uk en en en en fi ru en en en en en en en en en en en en en en en en en en en en en en uk en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en ms en en fr en es en de en en en nl en pt en es en de en es en en en en en en en fr cv es tr es en en en en ms en en en en en en fr en hbs_lat en en en en en en en fr cv es tr es en en en en de en en en ca en en en en en
You peeps rocked with helping me previously with a typescript gsap related issue so reaching out again after hours of pulling my hair out.
I am using typescript and vue and gsap in my app.
I need to disable a draggable but struggling how to store a reference to my draggable so I can disable it.
I tried using the following  which resulted in "Property 'disable' does not exist on type '{}' when I called this.draggable.disable()
data() { return { draggable: {}, proxy:new HTMLDivElement() } }
And also the following which resulted in the following error:
Type 'Draggable[]' is missing the following properties from type 'typeof _Draggable':
prototype, version, zIndex, create, and 3 more
data() { return { draggable: Draggable, proxy:new HTMLDivElement() } }
Any help would be much appreciated so I can manage to disable my draggable.
See the Pen OJzEOYj by antdev (@antdev) on CodePen
I don't know much about Vue, but I think you'd want:
That does indeed disable the draggable in my test on codepen.
See the Pen WNMNJvw by antdev (@antdev) on CodePen
Though on my actual app I have the following:
this.draggable = Draggable.create(this.proxy, { ... })[0];
So this.draggable.disable(); should have worked.
I wonder if the issues I am having with setting the type as Draggable is related to this in draggable.d.ts
I am pretty sure I have the latest version of gsap
8 hours ago, Antdev said:
That is not going cause any errors, and you really shouldn't worry about that property as it's really not documented.
Can you post your TypeScript code and why you think it's an error? You can use CodeSandbox if you really need to show the TypeScript error.
Share on other sites
Antdev    20 Likes (Newbie)
Thanks Blake for confirming the TODO code is not the issue.
I did as you suggested and created a CodeSandbox test that includes my code from my app
I am not experiencing the issue in this CodeSandbox test but still having the issue on my actual app where when I try to set the type of my draggable instance to Draggable I get the error:
TS2739: Type 'Draggable' is missing the following properties from type 'typeof _Draggable': prototype, version, zIndex, create, get
> 495 |       this.myDraggable = Draggable.create("#work-wheel4", {
this.myDraggable = Draggable.create("#work-wheel4", {
onDrag: () => this.updateProgress(this.myDraggable),
onThrowUpdate: () => this.updateProgress(this.myDraggable),
onThrowComplete: () => this.endThrow()
I have installed the latest bonus file and ran
My import statements are as follows:
import { defineComponent } from 'vue'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; import { InertiaPlugin } from 'gsap/InertiaPlugin'; import { Draggable } from 'gsap/Draggable'; import Config from './config.json'; gsap.registerPlugin(Draggable, InertiaPlugin, ScrollTrigger);
And this is where I set the data property
export default defineComponent({ name: 'App', data(){ return { myDraggable: Draggable,
Any idea why I am getting this error
Share on other sites
OSUblake    18,414 Likes (Superhero)
Yeah, that's weird. I have no idea why it might be doing that for you on your setup but not on CodeSandbox.
Just curious is using something like typeof Draggable works.
But you really don't even need to have myDraggable and the proxy in the data because you really don't need those to be reactive, so something like this should be fine. Also note that if you're only creating a single Draggable, you can use new Draggable instead of Draggable.create to get the instance.
Share on other sites
Antdev    20 Likes (Newbie)
I am curious when you say that I don't need myDraggable and proxy in data. If I remove myDraggable from data I get an error
TS2339: Property 'myDraggable' does not exist on type 'ComponentPublicInstance<{} | {}, {}, {
I tried using the new Draggable syntax but when I set the type of myDraggable in data to Draggable I still get the error
Issues checking in progress... ERROR in src/App.vue:241:7 TS2739: Type '_Draggable' is missing the following properties from type 'typeof _Draggable': prototype, version, zIndex, create, get 239 | 240 | > 241 | this.myDraggable = new Draggable(this.myProxy, { | ^^^^^^^^^^^^^^^^ 242 | trigger: ".scrollTarget", 243 | type: "x", 244 | inertia: true,
With regards the bit about whether typeof Draggable works, can you clarify how I would test this - do I add console.log(typeof Draggable) in say the mounted function?
Share on other sites
OSUblake    18,414 Likes (Superhero)
You shouldn't need to set the type if you exclude from the data as TypeScript should infer its type when you create the Draggable.
The typeof thing I was suggesting was just for the type, but  again, you really don't need to include myDraggable or the proxy in the data.
return { myDraggable: typeof Draggable, proxy: document.createElement("div"), };
If you're still getting errors, there must something unique to your setup because I cannot reproduce on my end. Do you think you can send me a simplified version of your project that shows the error? A zip or simple repo is fine.
Share on other sites
Antdev    20 Likes (Newbie)
Thank you very much Blake. I will try that now.
If that doesn't work I will send you a zip.
Share on other sites
Antdev    20 Likes (Newbie)
No joy - with that so have attached a zip
ERROR in src/App.vue:30:7 TS2322: Type 'Draggable' is not assignable to type '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"'. Type 'Draggable' is not assignable to type '"function"'. 28 | methods: { 29 | init: function () { > 30 | this.myDraggable = Draggable.create(this.proxy, { | ^^^^^^^^^^^^^^^^ 31 | trigger: ".wrapper", 32 | type: "x" 33 | })[0]; ERROR in src/App.vue:37:24 TS2339: Property 'disable' does not exist on type '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"'. Property 'disable' does not exist on type '"string"'. 35 | disableDraggable() { 36 | alert("disable draggable"); > 37 | this.myDraggable.disable(); | ^^^^^^^ 38 | } 39 | }); 40 |
Share on other sites
Antdev    20 Likes (Newbie)
OK I have made some progress setting myDraggable to an Array of Draggable as I am aware the Draggable.create returns an array
Then I needed to pass this.myDraggable[0] in my updateProgress function call
Still confused why the other way didn't work that worked in CodeSandbox didn't work in my app instance but at least now I can happily disable my draggable
Be still interested if you so look at the zip I uploaded if you discover anything but either way thank you very much for your timely responses.
data() { return { myDraggable: Array (), proxy: document.createElement("div"), }; }, mounted() { this.init(); }, methods: { init: function () { this.myDraggable = Draggable.create(this.proxy, { trigger: ".wrapper", type: "x", inertia: true, resistance: 0.75, dragResistance: 0.75, onDrag: () => this.updateProgress(this.myDraggable[0]), }); }, updateProgress(myDraggable) { var debug = document.getElementById("debug"); debug.innerHTML = "draggable.x: " + myDraggable.x; }, disableDraggable() { this.myDraggable[0].disable(); }, },
Share on other sites
OSUblake    18,414 Likes (Superhero)
Thanks, I'll check it out.
Share on other sites
Antdev    20 Likes (Newbie)
Thanks Blake - much appreciated.
Share on other sites
OSUblake    18,414 Likes (Superhero)
I think you might need to use the data thing if you want full TS support without going through a bunch of hoops. This is the exact issue, but there is no good solution as the type will always be any and you have to use $options.
Unless you add some custom types...
But, I can't believe I didn't see what the initial problem was. This is not setting the type. It's setting myDraggable to the actual class.
To get it to work, we actually need to define the type for the data object that is return by the function call. No errors here.
export default defineComponent({ name: 'App', data(): { myDraggable?: Draggable } { return { myDraggable: undefined, } }, mounted() { this.init(); }, methods: { init() { let proxy = document.createElement("div"); this.myDraggable = new Draggable(proxy, { trigger: ".wrapper", type: "x" }); }, disableDraggable() { this.myDraggable?.disable(); } } });
If anyone knows a cleaner way to do this in Vue 3 without having to use data, please do share 🙏
Share on other sites
Antdev    20 Likes (Newbie)
Thank you Blake for your dedication to helping me solve this conundrum. I think I will stick with the solution setting it as an array as that feels cleaner to me.
Hopefully there is no issue doing it this way?
Share on other sites
OSUblake    18,414 Likes (Superhero)
3 minutes ago, Antdev said:
Hopefully there is no issue doing it this way?
I mean, it's fine as long you remember that you're always going to be dealing with an array.
But I would still focus on my solution, because you may need to something similar to that in future. Like say you want to pause a Tween, how you would define that in the data?
export default defineComponent({ data() { return { myTween: ??????????? }; }, mounted() { this.myTween = gsap.to(".foo", { x: 300 }); }, methods: { pauseTween() { this.myTween.pause(); } } });
If you define that data type, it should be no issue.
export default defineComponent({ data(): { myTween?: gsap.core.Tween } { return { myTween: undefined }; }, mounted() { this.myTween = gsap.to(".foo", { x: 300 }); }, methods: { pauseTween() { this.myTween?.pause(); } } });
Share on other sites
OSUblake    18,414 Likes (Superhero)
I guess something like this, but still a little sketchy as we are defining an object and then changing it in mounted.
export default defineComponent({ data() { return { myTween: {} as gsap.core.Tween }; }, mounted() { this.myTween = gsap.to(".foo", { x: 300 }); }, methods: { pauseTween() { this.myTween?.pause(); } } });
Share on other sites
Antdev    20 Likes (Newbie)
Ah OK thanks Blake tho interestingly I have no problem with the following in my app
then in mounted I have
this.baseTl = gsap.timeline({ paused: true });
.timeline({ repeat: -1, paused: true })
Share on other sites
Antdev    20 Likes (Newbie)
Anyway yeah I agree your solution is the best option and I will go with that as I have several apps with this kind of stuff in it and I don't want to get stuck again
Share on other sites
OSUblake    18,414 Likes (Superhero)
Yeah, that's creating to 2 timelines. You creating one here.
And then overwriting the original one here.
console.log("baseTl", this.baseTl); // logs out the original timeline this.baseTl = gsap.timeline({ paused: true });
That's why I explicitly asked about a Tween because I knew you would do that with a Timeline 😉
Share on other sites
Antdev    20 Likes (Newbie)
Thanks again Blake - I need to read up more on typescript as my lack of knowledge has really hampered me with this project. However I believe the advantages it has brought me in organising all the data that populates my apps was worth the pain I am suffering. It is just frustrating when you are up against the clock to get stuck for days on a line of code
Share on other sites
OSUblake    18,414 Likes (Superhero)
Are you required to use TypeScript? Sometimes is more trouble than it's worth.
Share on other sites
Antdev    20 Likes (Newbie)
Unfortunately yes it is a requirement and I am on the home run now fortunately. I will think twice next time about using typescript with gsap
Share on other sites
Create an account or sign in to comment
You need to be a member in order to leave a comment
Sign up for a new account in our community. It's easy!
Register a new account
Already have an account? Sign in here.
Sign in to follow this   Followers 3
Go to topic listing
Recently Browsing   0 members
No registered users viewing this page.
Getting in a muddle with typescript and gsap
“I will never say it enough but @greensock you are absolutely amazing and you have no idea how much time and brain cells I have spared thanks to you 🥰”
“Go and browse through FWA or Awwwards, then view source of anything you see that has cool animation and you will be surprised how widely GSAP is used.”
“There is no doubt that GreenSock is currently the best available tool for creating astonishing interactive websites and animation effects.”
“Every time a new GSAP plugin is introduced, I'm close to bursting from excitement. The simplicity of the GreenSock API makes learning and applying these tools in projects such a dream.”
“GSAP has been absolutely the best experience for me as a newbie. The people in this community take serious time to help you with upcoming issues on real life projects like I've never experienced before.”
“I just tried to animate some objects using vanilla js but it was really laggy- switched to GSAP and now it’s smooth af”
“GSAP makes my job fun, because it allows me to focus on creating rich, engaging web experiences, while GSAP handles much of the implementation details behind the scenes.”
“I've never worked with a product that has such fantastic and enthusiastic support. GreenSock is incredible in its own right, but the team behind it is really what makes it shine.”
“It's shocking the @w3c didn't use @greensock as a model of how to do animation via code. Did they even ask animators what they use?”
Sign Up For Our Newsletter
Get the latest updates on GreenSock products, exclusive offers, and more right in your inbox.
Your information will always be kept confidential.
Thanks for signing up!
Now you'll begin receiving the latest GreenSock updates, exclusive offers, and more right in your inbox. Welcome aboard.