Exploring Angular's ng-transclude directive within a repeat loop

Recently, I began delving into AngularJS and attempted to create a custom table directive with multiple slots for transclusion. However, I encountered an issue where the scope was not being passed to the transclude. Although there are various solutions available on StackOverflow, none of them seem to work in my specific case where an ng-repeat is not present for the top element in the directive template. I am struggling to adapt these solutions to fit my requirements.

Here is a simplified version of the directive:

<span>
  <div>Some pagination</div>
  <div style="display: inline"><input type="text" placeholder="Search"/></div>
  <div style="display: inline">Some filters</div>

  <table>
    <tbody>
      <tr ng-repeat="line in lines" ng-transclude="row">
      </tr>
    </tbody>
  </table>

  <div>Some pagination again</div>
</span>

Usage of the directive:

<my-table>
     <row>
          <td>{{line.col1}}</td>
          <td>{{line.col2}}</td>
      </row>
</my-table>

View the full example and script on Plunkr: https://plnkr.co/edit/rg43ZdPMGHLBJCTLOoLC

Any guidance would be greatly appreciated.

Answer №1

If you want to access the $scope object created by the ng-repeat directly in a transcluded template, one way to do so is by using the $parent property:

<my-table>
  <td>{{$parent.line.col1}}</td>
  <td>{{$parent.line.col2}}</td>
</my-table>

The $parent property of the $scope created for a transcluded template refers to the $scope of the target template where the transcluded template is ultimately placed (in this case, the ng-repeat), even if the transcluded $scope is not a direct child of the target $scope due to transclusion. For more information on this topic, you can read this informative blog post.

You can see this concept in action in this working Plunkr example: https://plnkr.co/edit/LoqIMiQVZKlTt5epDnZF?p=preview.

Answer №2

To properly utilize the $transclude function and establish a new child scope for each line, it is imperative to manually handle these functions in your directive implementation. Additionally, when working with an isolated scope, make sure to pass lines as needed. The linking function should be structured similar to the following example:

link: function($scope, $element, $attrs, controller, $transclude) {
      var tbody = $element.find('tbody');

      $scope.$watch('lines', function (lines) {
        tbody.empty();

        lines.forEach(function (line) {
          var childScope = $scope.$new();
          childScope.line = line;

          $transclude(childScope, function (content) {
            tbody.append('<tr>');
            tbody.append(content);
            tbody.append('</tr>');
          }, null,  'row');
        });
      });
    }

Check out this Plunker for a live demo: https://plnkr.co/edit/MLNZOmoQyMazgIpluMqO?p=preview

However, this approach can be cumbersome as creating tables using this method involves intricate DOM manipulation. The structure may not easily align with the desired table layout due to limitations imposed by the transclusion process.

Answer №3

It's not necessary to use attributes to simplify and clean up the code:

<body ng-controller="tableCtrl">
   <h1>Table test</h1>
   <my-table lines="lines"></my-table>
 </body>

Your template:

<span>
      <div>Some pagination</div>
      <div style="display: inline"><input type="text" placeholder="Search"/></div>
      <div style="display: inline">Some filters</div>

      <table>
        <tbody>
          <tr ng-repeat="line in lines">
               <td>{{line.col1}}</td>
               <td>{{line.col2}}</td>
          </tr>
        </tbody>
      </table>

      <div>Some pagination again</div>
    </span>

Angular directive:

angular.module('myApp', [])
.directive("myTable", function() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {
      lines:'=lines',
      api: '@'
    },
    templateUrl: "template.html",
  };
})
.controller("tableCtrl", ['$scope', function($scope) {
  $scope.lines = [
    {col1: "testCol1", col2: "testCol2"},
    {col1: "testCol11", col2: "testCol21"}
    ];
}]);

Check out a working example on Plunkr: https://plnkr.co/edit/iMxRoD0N3sUXqmViHAQh?p=preview

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The connection between two arrays remains intact even after using the .push() method in JavaScript or Vue.js

I need help setting up two arrays containing dates. The first array should have the dates in string format, while the second array should contain the same dates but as date objects. methods: { test() { let employments = [ { begin: ...

The enigmatic jQuery AJAX glitch is craving additional arguments

My website uses jQuery's ajax function to handle user signups. Despite using similar code throughout the site, I encountered an error while trying to execute the code below: Error Message: uncaught exception: [Exception... "Not enough arguments" nsr ...

What is the best way to manage a download link that necessitates an Authorization token when using Angular?

I'm currently working with a REST API in combination with Angular. The issue I'm facing is related to post objects that include file attachments. Every time a user wants to download a file attachment, they must make a call to /get/file/{id}, but ...

Securely store files by encrypting them with Node.js before saving to the disk

At the moment, I am making use of the multer library to store files on the File system. This particular application is built using Node and Express. I currently have a process in place where I save the file on the server first and then encrypt it. After e ...

Obtaining the initial row information from jqGrid

If I use the getRowData method, I can retrieve the current cell content instead of the original data before it was formatted. Is there a way to access the original content before any formatting transformations are applied? Just so you know, I am filling t ...

"Encountering an error retrieving weather forecast API in JavaScript - issue with

I've been attempting to fetch the weather forecast API JSON in a similar manner to how I accessed the current weather API, but unfortunately, it doesn't seem to be working no matter what approach I take. let inOneDay = { fetchWeather: functio ...

Using JQuery to dynamically set dropdown option values from a JSON object

I have an HTML code snippet: $.ajax({ type: "POST", url: "hanca/hanca_crud.php", dataType: 'json', data: { id_hanca: id_hanca, type: "detail_hanca" }, //detail_hanca success: function(data) { var teks = ""; $.each( ...

Change the position of an HTML image when the window size is adjusted

My web page features a striking design with a white background and a tilted black line cutting across. The main attraction is an image of a red ball that I want to stay perfectly aligned with the line as the window is resized, just like in the provided gif ...

What is the best way to send JSON data from Express to a JavaScript/jQuery script within a Pug template?

Currently, I am facing a challenge in passing JSON data from an Express route to a .js file located within a .pug template. I have been attempting to solve this issue using the following method: The router: // Office Locations router.get('/office_lo ...

Is it possible to enable sorting for every column in the b-table component?

After reviewing the information on sorting per column in the bootstrap-vue documentation, I am curious if it is possible to enable sorting for the entire table. ...

What is the best way to retrieve promiseValue from the response array?

I've run into some challenges while using Promise.all() for the first time with two get-methods. When I check the response in my console log, I can see the data I'm trying to fetch under promiseValue. However, I'm unsure of how to access it. ...

Transform the default WordPress gallery into a stunning slideshow with FlexSlider 2 integration

Greetings, I am searching for a solution to modify the default WordPress gallery in order to integrate the FlexSlider 2 plugin. I specifically want to incorporate this module or feature from this link, but I have been unable to figure it out myself. Your ...

What could be causing this slider to malfunction in Firefox?

I have recently developed a slider on this page: While the slider functions smoothly in Chrome, I am facing compatibility issues with Firefox. Can anyone shed some light on why this might be happening? Here is the HTML, CSS, and JS code used for the slid ...

Remove dynamically inserted list item using a button

I have dynamically created an unordered list (<ul>) that adds list items (<li>) when a button is clicked, along with a remove button. Initially, the default list item should not contain a remove button so I added it in the script. SCRIPT $(d ...

Directive not found - unable to locate controller

The directive 'appContent' requires the controller 'appLeft', but it cannot be located. //app-nav(left) app.directive('appLeft', function () { return { restrict: 'E', replace: ...

Ways to retrieve text files prior to the webpage loading (synchronously)

I have a simple task at hand that I really want to accomplish - loading some glsl fragment shaders from the disk or server, and then initializing a WebGL web page. Web programming is not my forte; I usually prefer working on shaders and OpenGL in C++. If i ...

Pass the form data to a Bootstrap modal upon submission of the form

I'm attempting to retrieve form data and convert it to JSON to display in a modal dialog that opens on the Submit button click! This is my progress so far: HTML <form class="form-horizontal" id="configuration-form"> --irrelevant-- <button ...

Vue Method always executed (regardless of click event)

I'm fairly new to vue and still getting a grasp on the fundamentals of my code. Currently, I am facing an issue with a Method. It should only trigger when the user clicks on the button, but it seems to be triggered all the time. I even tried adding ...

Is it possible to establish a scope for jquery.ajaxSetup()?

Currently, I am working on a project involving numerous ajax calls with repetitive parameters. After some consideration, I am contemplating using jquery.ajaxSetup() to streamline the code. However, jQuery does not recommend this approach in their API docu ...

Ajax is capable of sending images as part of the data payload

I am attempting to send data via Ajax, and this data may include an image. Unfortunately, I do not have any forms, so I am unable to submit in the traditional way. Here is my HTML code: <input type="file" accept="image/png,image/jpg,image/jpeg,image/ ...