angularJs TypeError: Преобразование круговой структуры в JSON

У меня есть небольшое приложение AngularJs, например, так:

 // html

 <div ng-repeat="project in projects">
     <h3>{{ project.id }}</h3>
     <h3>{{ project.title }}</h3>
      <div ng-repeat="task in project.tasks">
          <h4>{{ task.id }}. {{ task.title }}</h4>
          <button class="btn btn-default" ng-click="showEditTask=true">Edit Task</button>
          <div class="box row animate-show-hide" ng-show="showEditTask">

              <h2>Create a New Task</h2>
              <form name="newTaskForm" class="form-horizontal">
                  Title: <br />
                  <input ng-model="new_task.title" type="text" id="title" name="title" class="form-control" placeholder="Title" required /><br />

                  Project: <br />
                  <select ng-model="new_task.project" ng-options="project.title for project in projects" class="form-control"></select><br>
              </form>

                  <button class="btn btn-success" ng-click="createTask(new_task)" ng-disabled="!newTaskForm.title.$valid">create</button>
          </div>
      </div>
 </div>


  // app.js

  concernsApp.factory('ConcernService', function ($http, $q) {

    ...

    update: function (obj_url, obj) {
        var defer = $q.defer();
        console.log(obj)
        $http({method: 'POST',
            url: api_url + obj_url + obj.id + '/',
            data: obj}).
            success(function (data, status, headers, config) {
                defer.resolve(data);
            }).error(function (data, status, headers, config) {
                defer.reject(status);
            });
        return defer.promise;
     },
   });


 concernsApp.controller('ProjectsCtrl', function ($scope, $http, ConcernService) {

    $scope.updateTask = function(obj) {
        ConcernService.update('tasks/', obj).then(function(){
        ...
    }
 });

Проблема в том, чтобы обновить задачу и оставить родительский проект как есть. Если я изменю родительский проект, все работает нормально. Если я использую тот же родительский проект, то получаю:

TypeError: Converting circular structure to JSON

Я не совсем уверен, что здесь происходит.

редактировать

Итак, я могу решить проблему следующим образом:

$scope.updateTask = function(obj) {
    parentProject = {'id': obj.project.id};
    obj.project = parentProject;
    ConcernService.update('tasks/', obj).then(function(){
        ...
    });
}; 

Это работает, так как мне нужен только task.project.id для обновления объекта. Я думаю, что проблема связана с тем фактом, что задача ссылается на родительский проект, который, в свою очередь, ссылается на дочерние задачи и т.д. Я не совсем уверен в этом сложном.

Тем не менее, это решение кажется мне немного хакерским, и я хотел бы увидеть лучшее решение.

Ответ 1

Где-то вы пытаетесь преобразовать объект в JSON, и в нем есть круговая ссылка, что означает что-то вроде этого:

var myObj = new Object();
myObject.reference = myObj;

Теперь попытка конвертировать это в JSON не удастся и приведет к вашей ошибке.

Посмотрев на отредактированный пост, ваша структура данных выглядит примерно так:

task.parent -> {project}

project.tasks -> [{task1},{task2},...]

Предполагается моделировать отношение "проект имеет несколько задач" и "задача принадлежит проекту".

Теперь это, очевидно, не может быть преобразовано в формат json из-за циклических ссылок.

Для структуры данных, почему бы не пойти с:

project = { "id": 42,
            "tasks": [123, 124, 127, ... ],
          }

task = { "id": 123,
         "idproject": 42,
            ...
       }

Всякий раз, когда вы должны показывать отношения в своем приложении angularjs, вы можете использовать фильтры. Если вы хотите показать, что принадлежит проекту, отфильтруйте все задачи с помощью projectid.

Или получить только необходимые данные из вашего бэкэнда "на лету", запросив, какие задачи имеет бэкенд для определенного идентификатора проекта.

Это один из способов сделать это. Конечно, если бэкенд принимает соответствующие запросы на обновление, он будет работать так же хорошо, например. для обновления проекта потребуется идентификатор проекта и массив идентификаторов задач.