Bilal Djaghout
Bilal Djaghout

Reputation: 176

Using AngularJS Trying to insert a <tr> in the middle

Here, I'm trying to insert a tr tag under a selected tr tag.I managed to insert the tr in the table but it was in the bottom. This is a sample code:

"use strict";

(function(angular) {
    var app = angular.module('app', []);
    app.controller('MainController', MainController);

    MainController.$inject = ['$compile', '$scope', '$templateCache'];

    function MainController($compile, $scope, $templateCache) {
        var publishShown = false;
        var lastItemAppned;
        var vm = this;
        vm.targets = ['Single passenger', 'Single driver', 'All passengers', 'All drivers'];
        vm.items = ["Cheese", "Pepperoni", "Black Olives"];
        vm.cancel = cancel;
        vm.fruits = [{
            name: 'Orange',
            color: 'Orange',
            tree: 'Orange Tree!',
            origin: 'China'
        }, {
            name: 'Apple',
            color: 'Green',
            tree: 'Apple Tree!',
            origin: 'Moon'
        }];
        vm.message = 'Fruit store!';

        function appendTemplate(event) {
            if (publishShown) {
                removeLastAppend();
            }
            publishShown = true;
            var template = $templateCache.get('template.html');
            var compiledHtml = $compile(template)($scope);
            var parent = event.currentTarget.parentElement.parentElement.parentElement;
            parent.append(compiledHtml[0]);
        }

        vm.showOptions = function(event) {
            appendTemplate(event);
        }

        function removeLastAppend() {
            angular.element('#publish-template').remove();
        }

        function cancel() {
            removeLastAppend();
        }

    }
})(window.angular);
<!DOCTYPE html>
<html ng-app="app">

<head>
    <link data-require="bootstrap-css@3.*" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
    <link data-require="bootstrap@*" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
    <script data-require="jquery@*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script data-require="Tether@*" data-semver="1.4.0" src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
    <script data-require="bootstrap@*" data-semver="4.0.5" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
    <script data-require="[email protected].*" data-semver="1.6.4" src="https://code.angularjs.org/1.6.4/angular.min.js"></script>
    <script data-require="[email protected].*" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-animate.js"></script>
    <script data-require="[email protected].*" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-touch.js"></script>
    <script data-require="ui-bootstrap@*" data-semver="2.5.0" src="https://cdn.rawgit.com/angular-ui/bootstrap/gh-pages/ui-bootstrap-tpls-2.5.0.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
</head>

<body ng-controller="MainController as vm">
    <script type="text/ng-template" id="template.html">
        <tr id="publish-template">
            <td colspan="5">
                <div class="row">
                    <div class="col-sm-3">
                        <button class="btn btn-sm btn-success" ng-click="vm.command()">Command</button>
                    </div>
                    <div class="col-sm-3">
                        <button class="btn btn-sm btn-primary" ng-click="vm.sell()">Sell</button>
                    </div>
                    <div class="col-sm-3">
                        <button class="btn btn-sm btn-warning" ng-click="vm.eatSome()">Eat some!</button>
                    </div>
                    <div class="col-sm-3">
                        <button class="btn btn-sm btn-danger" ng-click="vm.cancel()">Cancel</button>
                    </div>
                </div>
            </td>
        </tr>
    </script>
    <div class="container-fluid">
        <h1>{{vm.message}}</h1>
        <table class="table">
            <thead>
                <th>Name</th>
                <th>Color</th>
                <th>Tree</th>
                <th>Origin</th>
                <th>Action</th>
            </thead>
            <tbody>
                <tr ng-repeat="fruit in vm.fruits">
                    <td>{{fruit.name}}</td>
                    <td>{{fruit.color}}</td>
                    <td>{{fruit.tree}}</td>
                    <td>{{fruit.origin}}</td>
                    <td>
                        <button class="btn btn-primary" ng-click="vm.showOptions($event)">Options</button>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</body>

</html>

As you see, if you click the second options button, you'll not notice the problem, but if you click the first one, it adds a tr tag always in the bottom of the table!

My aim is to add the new tr under the selected on. Thanks in advance

Upvotes: 1

Views: 189

Answers (1)

Ashish Dhandharia
Ashish Dhandharia

Reputation: 361

The ng-repeat is running on the tr element and you are looking to break the loop and insert another tr in the middle based on the row that was clicked on. To achieve this you need to break the table into 3 parts

  • TR ng-repeat on topFruits
  • TR row with option buttons (will be hidden initially)
  • TR ng-repeat on bottomFruits

Initially, you will need to assign all the fruits to topFruits and keep the bottomFruits null. Also keep the tr row with the option buttons hidden.

When the show Options button is clicked on a row, get the index of the row and then divide the fruits between topFruits and bottomFruits based on the index. Also make the row with buttons visible.

Here is a working demo

Here is the HTML body

<body ng-controller="MainCtrl as vm">
    <div class="container-fluid">
        <h1>{{vm.message}}</h1>
        <table class="table">
            <thead>
               <tr>
                <th>Name</th>
                <th>Color</th>
                <th>Tree</th>
                <th>Origin</th>
                <th>Action</th>
              </tr>
            </thead>
            <tbody>
                  <tr ng-repeat="fruit in vm.topFruits">
                    <td style="background:#bbb">{{fruit.name}}</td>
                    <td>{{fruit.color}}</td>
                    <td>{{fruit.tree}}</td>
                    <td>{{fruit.origin}}</td>
                    <td>
                        <button class="btn btn-primary" ng-click="vm.showOptionsTop($index)">Options</button>
                    </td>
                  </tr>
                  <tr id="publish-template" style="display:none">
                    <td colspan="5">
                      <div class="row">
                        <div class="col-sm-3">
                          <button class="btn btn-sm btn-success" ng-click="vm.command()">Command</button>
                        </div>
                      <div class="col-sm-3">
                        <button class="btn btn-sm btn-primary" ng-click="vm.sell()">Sell</button>
                      </div>
                      <div class="col-sm-3">
                        <button class="btn btn-sm btn-warning" ng-click="vm.eatSome()">Eat some!</button>
                      </div>
                      <div class="col-sm-3">
                        <button class="btn btn-sm btn-danger" ng-click="vm.cancel()">Cancel</button>
                      </div>
                    </div>
                  </td>
                </tr>
                <tr ng-repeat="fruit in vm.bottomFruits">
                    <td  style="background:#fcc">{{fruit.name}}</td>
                    <td>{{fruit.color}}</td>
                    <td>{{fruit.tree}}</td>
                    <td>{{fruit.origin}}</td>
                    <td>
                        <button class="btn btn-primary" ng-click="vm.showOptionsBottom($index)">Options</button>
                    </td>
                  </tr>
            </tbody>
        </table>
    </div>
</body>

Here is the controller code

 vm.fruits = [{
            name: 'Orange',
            color: 'Orange',
            tree: 'Orange Tree!',
            origin: 'China'
        }, {
            name: 'Apple',
            color: 'Green',
            tree: 'Apple Tree!',
            origin: 'Moon'
        }];
        vm.topFruits = vm.fruits;
        vm.bottomFruits = [];
        vm.message = 'Fruit store!';

        function appendTemplate(index) {

            if (vm.publishShown) {
                removeLastAppend();
            }
            vm.publishShown = true;
            vm.topFruits = [];
            vm.bottomFruits = [];
            document.getElementById('publish-template').style.display="block";
            for(i=0;i<vm.fruits.length;i++) {
              if(i<=index) {
                vm.topFruits[i] = vm.fruits[i];
              } else {
                vm.bottomFruits[i-vm.topFruits.length] = vm.fruits[i];
              }
            }
        }

        vm.showOptionsTop = function(index) {
        appendTemplate(index);
    }
       vm.showOptionsBottom = function(index) {
        appendTemplate(index+vm.topFruits.length);
    }

        function removeLastAppend() {
            document.getElementById('publish-template').style.display="none";
            vm.publishShown = false;
        }

        function cancel() {
            removeLastAppend();
        }

Upvotes: 1

Related Questions