Displaying two instances of a repeated item using ng-repeat splice

Whenever I splice an object into my ng-repeat array, it mysteriously duplicates what I've spliced in and conceals the last object in the array.

Yet, if I toggle hide and "refresh" the ng-repeat, the correct data is displayed.

Can anyone shed light on why this is happening and suggest a solution?

angular.module('app', [])
  .controller('ctrl', function($scope) {
    $scope.workflow = {
      flow: [{
        "id": "1334f68db820f664",
        "step_number": 1,
        "tasks": [{
          "id": "1334f68e3f20f665"
        }]
      }, {
        "id": "134967a5ba205f5b",
        "step_number": 2,
        "tasks": [{
          "id": "134972c5b420e027"
        }]
      }, {
        "id": "1334f68e7d209ae6",
        "step_number": 3,
        "tasks": [{
          "id": "1334f68ef6209ae7"
        }]
      }]
    };

    $scope.insertStep = function() {

      var insertStepIndex = 1,
        task_data = {
          "id": null,
          "step_number": (insertStepIndex + 2),
          "tasks": []
        };

      //go through each item in the array
      $.each($scope.workflow.flow, function(index, step) {
        //if the step number is greater then the place you want to insert it into, increase the step numbers
        if (step.step_number > $scope.workflow.flow[insertStepIndex].step_number) step.step_number++;
      });

      $scope.workflow.flow.splice((insertStepIndex + 1), 0, task_data);

    }

    $scope.toggleHide = function() {
      $scope.hide = !$scope.hide;
    }


  });
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.js"></script>
<div ng-app="app" ng-controller="ctrl">

  <div ng-click="insertStep()">Insert Step</div>
  <br />
  <br />

  <div ng-click="toggleHide()">Toggle Repeat</div>
  <br />
  <br />

  <div ng-if="!hide">
    <div ng-repeat="data in workflow.flow | orderBy:'+step_number'" ng-init="$stepIndex = workflow.flow.indexOf(data)">
      {{ workflow.flow[$stepIndex].step_number }}
    </div>
  </div>
</div>

Answer №1

After closely examining the issue, it appears that the root of the problem lies in the behavior of the ng-init directive. This directive only executes once, which means that any assignment like

$stepIndex = workflow.flow.indexOf(data)
will not be updated when new data is added to the array or list.

To resolve this issue, introducing a scope function is the key. By doing so, Angular will automatically call the function whenever its returning value changes.

angular.module('app', [])
  .controller('ctrl', function($scope) {
    $scope.workflow = {
      flow: [{
        "id": "1334f68db820f664",
        "step_number": 1,
        "tasks": [{
          "id": "1334f68e3f20f665"
        }]
      }, {
        "id": "134967a5ba205f5b",
        "step_number": 2,
        "tasks": [{
          "id": "134972c5b420e027"
        }]
      }, {
        "id": "1334f68e7d209ae6",
        "step_number": 3,
        "tasks": [{
          "id": "1334f68ef6209ae7"
        }]
      }]
    };

    $scope.insertStep = function() {

      var insertStepIndex = 1
      var task_data = {
        "id": null,
        "step_number": (insertStepIndex + 2),
        "tasks": []
      };

      //go through each item in the array
      angular.forEach($scope.workflow.flow, function(step, index) {
        //if the step number is greater then the place you want to insert it into, increase the step numbers
        if (step.step_number > $scope.workflow.flow[insertStepIndex].step_number) step.step_number++;
      });

      $scope.workflow.flow.splice((insertStepIndex + 1), 0, task_data);

    }

    // A newly added function to address the issue
    $scope.getIndex = function(data) {
      return $scope.workflow.flow.indexOf(data);
    };

    $scope.toggleHide = function() {
      $scope.hide = !$scope.hide;
    };

  });
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.js"></script>
<div ng-app="app" ng-controller="ctrl">

  <div ng-click="insertStep()">Insert Step</div>
  <br />
  <br />

  <div ng-click="toggleHide()">Toggle Repeat</div>
  <br />
  <br />

  <div ng-if="!hide">
    <div ng-repeat="data in workflow.flow | orderBy:'+step_number'">
      {{ workflow.flow[getIndex(data)].step_number }}
    </div>
  </div>
</div>

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

Setting response query correctly in Solr using AJAX

Inspired by an example of using Solr's JSON output for AJAX, I have incorporated a drop-down menu into my project form and introduced faceting to the parameters. Parameters: function getstandardargs() { var params = [ 'wt=json' ...

Developing Functions using MongoDB Console

When running the query db.graduates.find({student_id: '2010-01016'}).pretty(), it returns a result. Afterwards, I created a function: function findStud(name,value){ return db.graduates.find({name:value}); } However, while executing findStud("s ...

The value of .val() is a combination of various values

I am currently working on a code that involves showing/hiding elements based on the selection of a value in a <select> tag. My next task is to modify it so that the class is added if .val() is equal to not only '16' but also '14' ...

Currency format Material Design Input

Are there any input options within Material Design that support specific formats like currency? If this feature is not available, what alternatives would you recommend to achieve the desired functionality? Appreciate your help. ...

Translate unknown provider in Angular using $translateProvider

Here is the situation I am facing: I am working on an Ionic project and I want to implement internationalization using angular-translate. To achieve this, I have added angular-translate.min.js to my project: <script src="lib/ionic/js/ionic.bundle.js"&g ...

Is it possible to automatically set focus on the input box in an html tag multiple times instead of just once with autofocus?

Currently, I am developing an online editor that allows users to quickly edit individual words. My approach involves replacing specific words with input boxes containing the word for direct editing by users. In order to streamline the process and ensure e ...

Loading SVG images in advance

I am in possession of around one hundred simple SVG images, distributed among five different image folders. These images are currently retrieved on demand when they need to be displayed, which generally works well but occasionally results in flickering tha ...

Using Angular to send data to a WCF JSON endpoint

I've been trying to send a request to a WCF JSON service endpoint from Angular, but I haven't had any luck so far. The service has been tested through other methods and is functioning properly for the specified URL. When checking with Firebug, I ...

Convert form data into a JSON object using Vue.js

I'm attempting to generate a JSON object from the submitted form data. Fortunately, I've accomplished this using a variable. However, is there an alternative approach for creating a JSON object? Form <form @submit.prevent="submit"& ...

What methods can be utilized to avoid displaying a Bootstrap popover intermittently within an AngularJS framework?

When using the bootstrap popover in a custom AngularJS directive, I need to display an error message when the button is disabled by setting $scope.buytypeButton= {type:false}. The error message should be displayed in a popover. On the other hand, when $sco ...

What is the best way to gradually show the contents of the second div starting from the bottom?

I want to create a scrolling effect where the contents of the second div are revealed as if they were fixed on the first div, similar to Conichi View example in JSFiddle .one { width: 768px; height: 700px; color: white; background-color: black; ...

Issues encountered when running a Vue.js project that already exists

I'm encountering an issue while trying to launch a pre-built UI project using vue.js. Despite having Python installed with the environment variable properly set, I keep getting an error when running the npm install command. How can this be resolved? n ...

How can I implement draggable and resizable <div> elements to create resizable columns in an antd table using React?

I am currently utilizing the Reacts Antd library to showcase the contents of my table. I am interested in implementing a feature that allows me to resize the column widths. To achieve this, I have wrapped the column in my element as depicted below. The dr ...

Node.js applications on Openshift frequently encounter 503 errors

I am currently in the process of setting up my initial Node.js + express web application utilizing Openshift's complimentary service. After installing node + npm and Openshift tools on my computer, I attempted to run my application. It functions perf ...

AngularJS - smooth scrolling with $anchorScroll duration

While going through the AngularJS documentation, I have not been able to determine whether $anchorScroll has a duration or easing option for smoother scrolling to elements. The documentation only shows: $location.hash('bottom'); // call $ancho ...

Retrieve the chosen date from a DatePicker using a Javascript function

Is there a way to retrieve the user-selected date using a JS function? I attempted this method: var test = $("#datepicker").datepicker( 'getDate' ); However, when I display it with an alert, it shows [object object] instead of the date. This ...

Tips on integrating alert functionality with ajax form submission

My method of submitting a form involves using ajax, with the following code to confirm the submission and display a message on the same page within HTML: $.ajax({ type: "POST", url: "process.php", da ...

Filter the ng-options by the value in a separate dropdown menu

I am having trouble with this code, even though it seems straightforward. My goal is to filter the 'model' dropdown based on the selected 'make'. Make: <select ng-model="makeng" ng-options="option.display for option in ...

Add Text to HTML and Delete Added Content Upon Button Click

I have successfully implemented code that appends new content to the div "users". However, I am facing an issue with removing the appended content when a user clicks a button. Currently, the code only removes the "remove" button upon clicking. But I need ...

Having trouble uploading an image URL into a Vue component?

I'm currently facing an issue while creating a Vue tag component, as I am unable to pass the source to the template html <card aposter="assets\images\poster.png" aname="a title"> </card> JavaScript Vue ...