0

I'm trying to add multiple angular controllers within the same tr tag, the problem is that chrome rewrites the table to standardize it, and there is no element between tr and td in the HTML table hierarchy.

Here is what I currently have, each color represents a different controller to call. enter image description here The final aim is to have a table like below, with a different controller for one or multiple td, instead or multiple trs angular_tr_td

I know I could use a global controller to handle all the data, or use multiple div elements with a fixed width to achieve this, but I'd prefer using a single tr table.

Here is the code :

<table>
    <tr>
        <div ng-controller="testController">
            <td>{{testcontrollerscopevalue}}</td> <!-- empty when displayed -->
            <td>{{testcontrollerscopevalue2}}</td> <!-- empty when displayed -->
            <td>{{testcontrollerscopevalue3}}</td> <!-- empty when displayed -->
        </div>
        <div ng-controller="testController2"> 
            <td>{{testcontroller2scopevalue}}</td> <!-- empty when displayed -->
        </div>
    </tr>
</table>

The following works :

 <table ng-controller="testController">
        <tr>
            <td>{{testcontrollerscopevalue}}</td> <!-- set when displayed-->
        </tr>
    </table>

Here is what chrome generates :

<body>
<div ng-controller="testController"></div>
<div ng-controller="testController2"></div>
<table>
    <tbody>
    <tr>
        <td>{{testcontrollerscopevalue}}</td> <!-- out of scope-->
        <td>{{testcontrollerscopevalue2}}</td> <!-- out of scope-->
        <td>{{testcontrollerscopevalue3}}</td> <!-- out of scope-->
        <td>{{testcontroller2scopevalue1}}</td> <!-- out of scope-->
    </tr>
    </tbody>
</table>

 <table ng-controller="testController">
        <tbody>
        <tr>
            <td>{{testcontrollerscopevalue}}</td> <!-- set -->
        </tr>
        </tbody>
    </table>

Is there any way I can achieve this ? Is there any tag I could use instead of div to get this to work? Thanks,

overlox
  • 794
  • 1
  • 5
  • 18
  • 1
    why would you need two controllers for one table body in the first place? what is the **real** problem you are trying to solve? – Claies Sep 15 '15 at 22:50
  • 1
    the update (with blurry screenshot) doesn't really explain why you are trying to show data from multiple different controllers; however, if the only choice in your design is that each of these "components" have it's own controller, you should probably consider making each a directive. – Claies Sep 15 '15 at 22:54
  • honestly, this looks to me like the wrong way to approach an angular app anyway; In angular, you shouldn't be concerned with how the DOM gets populated; rather, you should be considering how to populate your data, and the DOM should take a backseat to the data design. If you have data scattered across multiple controllers, it doesn't seem like the app logic is sound. (this may not be the case, but this pseudocode here doesn't demonstrate why this separation is necessary). – Claies Sep 15 '15 at 22:57
  • I'm using different APIs to fetch data from different services, td1, td2, td3 will be fetched from a service called in testController, td3, td4, td5 from testController2. I want to use a single tr table to make sure all the width is distributed properly. Sorry about the blurry screenshot. – overlox Sep 15 '15 at 23:01
  • 1
    Why not update scope variables in one controller from multiple services? – Jorg Sep 15 '15 at 23:02
  • 1
    well you can certainly nest controllers, but unless you are using the ControllerAs syntax, you won't be able to tell which scope is which. also, as I mentioned before, you could create directives which have their own controllers unique to their template, though I'm not sure that overcomes scattered data. – Claies Sep 15 '15 at 23:04
  • 2
    bottom line, what you are trying to do by having a `
    ` as an element inside a `` isn't a supported HTML construct, so it really wouldn't be something angular has a fix for, and it doesn't just affect chrome.
    – Claies Sep 15 '15 at 23:08
  • @jorg, since I have specific actions/buttons to call for each different API provider, I'd prefer to still have different controllers called. I'm trying to avoid a global controller, please see the updated post – overlox Sep 15 '15 at 23:18
  • @Claies, thanks, didn't know it was not chrome only. – overlox Sep 15 '15 at 23:21
  • 1
    if every `` is a separate controller (as it appears to be in the newest screenshot), you could just add `ng-controller` on the `` element itself. However, this still doesn't explain why you are so adamant that your data being separated and using a table is the only way to go, to the point that you go completely against angular design principles to get there. – Claies Sep 15 '15 at 23:51
  • @claies, Thanks for your help - I am just wondering if it's possible to do this with angular, if not I'll do it another way. If you are certain that it's not possible to do this cleanly, post an answer and I'll accept it. – overlox Sep 16 '15 at 00:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89750/discussion-between-claies-and-overlox). – Claies Sep 16 '15 at 00:41

2 Answers2

1

You should probably just do:

<td ng-controller="testController2">{{testcontrollerscopevalue}}</td>

If you really need the div:

<td><div ng-controller="testController2">{{testcontrollerscopevalue}}</div></td>
dave
  • 62,300
  • 5
  • 72
  • 93
1

As we discussed at length in the chat session, This is a case where you are best served by using the ControllerAs Syntax, and wrapping the <table> element in multiple <div> elements holding each controller's logic.

My suggestion was something similar to the following code:

<div ng-controller="testController as tc">
  <div ng-controller="testController2 as tc2">
    <table>
      <tbody>
        <tr>
          <td>{{tc1.testcontrollervalue}}</td>
          <td>{{tc1.testcontrollervalue2}}</td>
          <td>{{tc1.testcontrollervalue3}}</td>
          <td>{{tc2.testcontroller2value1}}</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

For this to work, your variables need to be converted to be properties of the controller, rather than properties of $scope.

var tc1 = this; //consistent reference to controller object
SomeService.get(function(data) {
  tc1.someProperty = data;
});
Community
  • 1
  • 1
Claies
  • 22,124
  • 4
  • 53
  • 77