Read on Angularjs official site explanation :
@ or @attr – bind a local scope property to the value of DOM
attribute. The result is always a string since DOM attributes are
strings. If no attr name is specified then the attribute name is
assumed to be the same as the local name. Given and widget definition of scope: { localName:’@myAttr’ },
then widget scope property localName will reflect the interpolated
value of hello {{name}}. As the name attribute changes so will the
localName property on the widget scope. The name is read from the
parent scope (not component scope).
So you can send only a string, to pass an object, you need to set-up a bi-directionnal binding using =.
scope: {
details: '=',
},
And your HTML will looks like
<div teamspeak details="data.details"></div>