EnigmaRM
EnigmaRM

Reputation: 7632

Access the 'value' in JS Object using D3.JS

I'm working with D3.js and trying to sort my bars in ascending/descending order when a button is clicked. But I'm having issues having the sortBars function return the correct value from my object.

var sortOrder = false;
var sortBars = function() {
sortOrder = !sortOrder;
svg.selectAll("rect")
    .sort(function(a, b) {
        if (sortOrder) {
            return d3.ascending(a, b);
        } else {
            return d3.descending(a, b);
        }
    })
    .transition()
    .delay(function(d, i) {
        return i * 50;
    })
    .duration(1000)
    .attr("x", function(d, i) {
        return xScale(i);
    });
}; 

When it returns xScale(i), I know it's not referencing my dataset appropriately. I've tried placing it as i.value (which is what I have it named as in my dataset). I know this isn't correct, but when I change it to that, I at least get the bars to move. How would I access the correct datum?

I've developed a JSFiddle for this. Feel free to play around with it. Currently, the Sort button won't have any effect (as the function is not correctly accessing the data yet).

Upvotes: 1

Views: 213

Answers (2)

Superboggly
Superboggly

Reputation: 5834

I think you are pretty close. The xscale should be using i - which here is the position of the datum in the list (not the datum which is in d). However your sort is trying to sort the data objects, not the values. Try this:

.sort(function(a, b) {
    if (sortOrder) {
        return d3.ascending(a.value, b.value);
    } else {
        return d3.descending(a.value, b.value);
    }
})

I think with two objects it is undefined which one is bigger. And the ascending and descending functions do not take accessors.

Upvotes: 1

Pablo Navarro
Pablo Navarro

Reputation: 8264

Your code was almost good, there are just two details:

The comparator function must return positive, negative or zero. In your code you are comparing data items, not their values:

function sortItems(a, b) {
   if (sortOrder) { return a.value - b.value; }
   return b.value - a.value;
}

svg.selectAll('rect')
.sort(sortItems)
// update the attributes

The sortBars method wasn't working. I prefer to bind the event using d3:

// Bind the event 'onclick' to the sortBars functions
d3.select('#sort').on('click', sortBars);

I forked your jsFiddle and adapted to make it work: http://jsfiddle.net/pnavarrc/3HL4a/4/

References

Upvotes: 1

Related Questions