Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to translate 'this' in D3 JavaScript to TypeScript?

I know that 'this' in JavaScript has a different meaning than in in TypeScript, as per this article 'this' in TypeScript. I have the following code in JavaScript used to create a thicker stroke on the selected node, and give all other nodes a smaller stroke.

node.on('click', function (d) {
   d3.selectAll('circle').attr('stroke-width', 1.5);
   d3.select(this).select('circle').attr('stroke-width', 5);
})

In TypeScript I have

this.node.on('click', (d:any) => {
   this.node.selectAll('circle').attr('stroke-width', 1.5);
   [this is where I need help].select('circle').attr('stroke-width', 5);
}
like image 959
H. Trujillo Avatar asked Apr 21 '17 19:04

H. Trujillo


People also ask

Why can’t I use typescript with D3?

This is because TypeScript has trouble importing .json files easily, though it can parse JSON strings. Using a .ts file and exporting it as an object is less hassle and works for what we need. One of the first things you might realize is that D3 uses a lot of .select or .selectAll operations.

How to convert existing JavaScript to TypeScript?

Converting Existing JavaScript to TypeScript Add tsconfig.json File to Project. First, we will add a tsconfig.json file to our project. This file manages the... Integrate with a build tool. Most JavaScript projects have an integrated build tool like webpack or gulp. For other... Converting .js files ...

How do I translate a D3 transformation?

D3.js transform.translate () Function. The transform.translate () function in D3.js library is used to get the transformation whose translation tx1 and ty1 is equal to tx0 + tk x and ty0 + tk y, where tx0 and ty0 is the transform’s translation and tk is the transform’s scale.

Why does typescript need to know the types of all objects?

Most JavaScript projects use third-party libraries like jQuery or Lodash. TypeScript needs to know the types of all objects in these libraries in order to compile files. Fortunately, TypeScript Type definition files for most JavaScript libraries are already available at DefinitelyTyped. So, we don't need to add types to these ourselves.


2 Answers

As already stated in this comment and this answer, this does not have a different meaning between JavaScript and TypeScript.

That being said, your problem here is way more prosaic: you're trying to use this in an arrow function to get the current DOM element, and that will simply not work.

So, in a nutshell, the problem here is the difference of this between an arrow function and a regular function, not between TypeScript and JavaScript.

Solution

There is an alternative to this, described everywhere in the API: when you use an anonymous function in most of D3 methods, the arguments being passed are...

... the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i]).

Thus, this is simply the current index (the second argument) of the nodes groups (the third argument).

So, in the snippet below:

selection.on("foo", function (d, i, n){
    console.log(this)
    console.log(n[i])
})

The two console.log will return the same thing.

As you are using an arrow function, the solution is (in JavaScript):

this.nodes.on("click", (d, i, n) => {
    d3.select(n[i])//rest of your code here
})

If you want to read more about the use of the second and the third arguments to get the DOM element, have a look at this example: d3 v4 retrieve drag DOM target from drag callback when `this` is not available

like image 103
Gerardo Furtado Avatar answered Sep 24 '22 19:09

Gerardo Furtado


The premise of this question, How to translate 'this' in D3 JavaScript to TypeScript?, is false. I did not downvote because it is important to educate.

I just want to clarify that this is 100% identical in TypeScript and JavaScript

In fact, all TypeScript syntax that is also valid JavaScript syntax has the exact same semantics.

This is what makes TypeScript a superset of JavaScript.

Update: I actually will amend this with an answer because the problem was that you thought the meaning was different. You are confused about arrow function syntax

(params) => expression or block

First of all => is not a TypeScript feature, but a JavaScript feature.

Secondly, TypeScript, as noted above naturally support both forms. This means that no translation is needed.

this means the same thing in TypeScript as it does in JavaScript.

In both languages it means something different in the context of => than it does in the context of function. There are many, many answers explaining this on SO, so I won't repeat them.

So here is the answer to this question.

If you have this file:

d3-app.js

node.on('click', function (d) {
  d3.selectAll('circle').attr('stroke-width', 1.5);
  d3.select(this).select('circle').attr('stroke-width', 5);
});

It works and you want to rewrite it in TypeScript.

Here is what you do:

  1. rename d3-app.js to d3-app.ts

That is all.

like image 45
Aluan Haddad Avatar answered Sep 21 '22 19:09

Aluan Haddad