Как добавить идентификатор объекта в другой объект с помощью AngularJS

У меня есть два объекта, события и комментарии:

   {
    "name": "events",
    "fields": {
      "name": {
        "type": "string"
      },
      "date": {
        "type": "datetime"
      },
      "time": {
        "type": "datetime"
      },
      "info": {
        "type": "text"
      },
      "users": {
        "collection": "users_events",
        "via": "event"
      },
      "eventCommentsId": {
        "collection": "comments",
        "via": "eventId"
      },
    }
  },
  {
    "name": "comments",
    "fields": {
      "content": {
        "type": "text"
      },
      "owner": {
        "object": "users"
      },
      "eventId": {
        "object": "events"
      },
      "date": {
        "type": "datetime"
      }
    }
  }

Каждое событие должно иметь свою уникальную коллекцию комментариев. Итак, это отношение «один ко многим».

Прямо сейчас я могу просто получить все комментарии, а не только те, которые относятся к каждому событию. Я думаю, что мне нужно включить идентификатор события в каждый комментарий. Но я не совсем уверен, как это сделать.

Если бы кто-нибудь мог помочь мне с этим, это было бы потрясающе!

Я создаю приложение с помощью Ionic/AngularJS и сохраняю свои данные с помощью Backand.

Заранее спасибо!

.controller('EventDetailCtrl', ['$scope', '$stateParams', '$ionicSideMenuDelegate', 'EventService', 'CommentService',function($scope, $stateParams, $ionicSideMenuDelegate, EventService, CommentService) { 
  $scope.openMenu = function () {
    $ionicSideMenuDelegate.toggleLeft();
  };    

  var id = $stateParams.id;
  EventService.getEvent(id).then(function(response){
   $scope.event = response.data;
});

  $scope.comments = [];
  $scope.input = {};

  function getAllComments() {
    CommentService.getComments()
    .then(function (result) {
      $scope.comments = result.data.data;
    });
  }

  $scope.addComment = function() {
    CommentService.addComment($scope.input)
    .then(function(result) {
      $scope.input = {};
      getAllComments();
    });
  }

  $scope.deleteComment = function(id) {
    CommentService.deleteComment(id)
    .then(function (result) {
      getAllComments();
    });
  }

  getAllComments();

}])

.service('CommentService', function ($http, Backand) {    
  var baseUrl = '/1/objects/';
  var objectName = 'comments/';

  function getUrl() {
    return Backand.getApiUrl() + baseUrl + objectName;
  }

  function getUrlForId(id) {
    return getUrl() + id;
  }

  getComments = function () {
    return $http.get(getUrl());
  };

  addComment = function(event) {
    return $http.post(getUrl(), event);
  }

  deleteComment = function (id) {
    return $http.delete(getUrlForId(id));
  };

  getComment = function (id) {
    return $http.get(getUrlForId(id));
  };


  return {
    getComments: getComments,
    addComment: addComment,
    deleteComment: deleteComment,
    getComment: getComment
  }   
})

person Community    schedule 24.03.2016    source источник
comment
Лучше делать это со стороны бэкенда, а не на JS (angularjs)!   -  person Bettimms    schedule 25.03.2016


Ответы (3)


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

http://mysite/getComments?eventId=2533213

И в вашей схеме комментариев (для БД) вы можете иметь одно поле как eventId. Затем вы можете получить все комментарии, имеющие идентификатор события, указанный в вызове, из БД и вернуться в свое приложение в ответ.

В интерфейсе вы можете сделать:

Контроллер:

function getCommentsById(event) {
    CommentService.getCommentsById(event)
    .then(function (result) {
      $scope.comments = result.data.data;
    });
  }

Сервис:

getCommentsById = function (event) {
    return $http.get(getUrl() + "?eventId=" + event.id); //supposing you have event.id
  };
person Muhammad Ahsan Ayaz    schedule 25.03.2016

Вы также можете создать запрос на панели управления Backand и назвать его как GetCommentsByEventId, а с конечной точкой API Backand.getApiUrl() + '/1/query/data/GetCommentsByEventId' вы можете передать идентификатор и получить комментарии для этого события. (см. скриншот ниже) скриншот запроса

В запросе с SQL SELECT * FROM comments WHERE event='{{eventId}}' вы получите комментарии для этого идентификатора события.

Или вы можете использовать фильтр в URL-адресе API, например Backand.getApiUrl() + /1/comments?filter={"fieldName":"event","operator":"in", "value": "33"} (здесь URL-адрес не закодирован для удобства чтения, 33 - это идентификатор события)

Моя модель БД для демонстрации выглядит так, как показано на этом снимке экрана: screenshot db model

И модель БД json выглядит следующим образом:

    [
{
    "name": "users",
    "fields": {
        "email": {
            "type": "string"
        },
        "firstName": {
            "type": "string"
        },
        "lastName": {
            "type": "string"
        },
        "user": {
            "collection": "comments",
            "via": "user"
        }
    }
},
{
    "name": "events",
    "fields": {
        "title": {
            "type": "string"
        },
        "created_at": {
            "type": "datetime"
        },
        "eventId": {
            "collection": "comments",
            "via": "event"
        }
    }
},
{
    "name": "comments",
    "fields": {
        "event": {
            "object": "events"
        },
        "user": {
            "object": "users"
        },
        "text": {
            "type": "string"
        }
    }
}
]

В модели БД я бы только переименовал eventId в модели events в eventCommentsId, чтобы было ясно, что это ссылка на комментарии.

Пожалуйста, найдите демонстрационный код ниже (не работает здесь, небезопасная работа в скрипте Backand) или работающую демонстрацию в этом jsfiddle< /а>.

Код angular можно немного изменить, но он работает. Если что-то еще не так, пожалуйста, дайте мне знать, потому что это мой первый пример с Backand.

Также в демо нет логина пользователя, поэтому все будет добавлено с userId = 1.

angular.module('demoApp', ['ionic', 'backand'])
  //Update Angular configuration section
  .config(function(BackandProvider) {
    BackandProvider.setAppName('myfirstapp123');
    //BackandProvider.setSignUpToken('-token-');
    BackandProvider.setAnonymousToken('9f99054f-3205-426b-afc7-158d7ac3500f');
  })
  .controller('mainController', MainController)
  .service('dataService', dataService)
  .factory('commentsFactory', Comments);

function MainController($scope, $http, Backand, dataService, commentsFactory) {
  var vm = this,
    comment = commentsFactory;

  vm.currentUserId = 1; //<<<< should be the current user later (no login yet)

  vm.displayedComments = {};
  dataService.getList('events').then(function(response) {
    vm.events = response.data;
  }); //eventsFactory;

	vm.addEvent = function(newTitle) {
  	
    if (!newTitle) return; // don't add empty events
  	// this should be in a factory later
    var newDate = new Date();
    
    return $http({
        method: 'POST',
        url: Backand.getApiUrl() + '/1/objects/events?returnObject=true',
        data: {
          title: newTitle,
          created_at: newDate
        }
      }).then(function(response) {
      	//console.log(response, vm.events);
      	vm.events.data.push(response.data);
      });
  }
  vm.addComment = function(userId, event, text) {
    //event.comments.push(
    if (!text) return;
    
    comment.create(userId, event.id, text).then(function(response) {
      event.comments.push(response.data);
      //console.log(response);
    });
  }

  vm.getComments = commentsFactory.getComments;
  vm.showComment = function(event) {
    //console.log(event);
    commentsFactory.getComments(event.id).then(function(response) {
      vm.displayedComments[event.id] = !vm.displayedComments[event.id];
      event.comments = response.data;
    });
  };
  vm.remove = function(event, commentId) {
  	console.log('removing', event, commentId);
  	commentsFactory.delete(commentId).then(function(response){
    	//console.log('removed', response, event);
      // next update collection in angular
      event.comments = event.comments.filter(function(comment) {
      	return comment.id !== commentId; // remove comment
      });
    });
  }
}

function dataService($http, Backand) {
  var vm = this;
  //get the object name and optional parameters
  vm.getList = function(name, sort, filter) {
    return $http({
      method: 'GET',
      url: Backand.getApiUrl() + '/1/objects/' + name,
      params: {
        pageSize: 20,
        pageNumber: 1,
        filter: filter || '',
        sort: sort || ''
      }
    });
  }
}

function Comments($http, Backand) {
  return {
    create: function(user, event, text) {
      return $http({
        method: 'POST',
        url: Backand.getApiUrl() + '/1/objects/comments?returnObject=true',
        data: {
          event: event,
          user: user,
          text: text
        }
      });
    },
    delete: function(commentId) {
    	return $http({
        method: 'DELETE',
        url: Backand.getApiUrl() + '/1/objects/comments/' + commentId
      });
    },
    getComments: function(id) {
      return $http({
        method: 'GET',
        url: Backand.getApiUrl() + '/1/query/data/GetCommentsByEventId',
        params: {
          parameters: {
            eventId: id
          }
        }
      });
    }
  }
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.2.4/css/ionic.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.2.4/js/ionic.bundle.js"></script>
<script src="https://cdn.backand.net/backand/dist/1.8.2/backand.min.js"></script>

<div ng-app="demoApp" ng-controller="mainController as mainCtrl">

  <ion-header-bar align-title="center" class="bar-dark">
    <h1 class="title">EventsApp</h1>
   </ion-header-bar>
  <ion-content>
    <!--<pre>{{mainCtrl.events | json : 2}}</pre-->
    <!--<pre>{{mainCtrl.displayedComments|json:2}}</pre>-->
    <ion-list>
      <ion-item>
      <form ng-submit="mainCtrl.addEvent(mainCtrl.newEventTitle); mainCtrl.newEventTitle = '';">
        <input type="text" ng-model="mainCtrl.newEventTitle" placeholder="event title..."/>
        <button class="item item-icon-left">
          <i class="icon ion-plus-round"></i>
          add event
        </button>
      </form>
      </ion-item>
      <ion-item ng-if="mainCtrl.events.data.length === 0">
        <h1>
        There are no events yet.
        </h1>
      </ion-item>
      <ion-item ng-repeat="event in mainCtrl.events.data | orderBy: '-created_at'" class="item item-button-right">
        <h1>
          {{event.title}}
        </h1>
        <button ng-click="mainCtrl.showComment(event)" class="button icon-left ion-ios-chatbubble" title="{{mainCtrl.displayedComments[event.id]? 'hide comments': 'show comments'}}">
        </button>
        <div ng-show="mainCtrl.displayedComments[event.id]" class="list">
          
          <form ng-submit="mainCtrl.addComment(mainCtrl.currentUserId, event, commentText)">
            <label class="item item-input">
              <span class="input-label">Username</span>
              <input type="text" disabled ng-model="mainCtrl.currentUserId">
            </label>
            <label class="item item-input">
              <span class="input-label">Comment</span>
              <input type="text" ng-model="commentText">
            </label>
            <button class="button button-positive">
               leave comment
            </button>
          </form>
          
          <ion-list>
            <ion-item ng-if="event.comments.length === 0">
              <h2>
              No comment yet. Be the first and leave a comment.
              </h2>
            </ion-item>
            <ion-item ng-repeat="comment in event.comments">
            <div class="item item-button-right">
            user {{comment.user}} wrote {{comment.text}}
              <button ng-click="mainCtrl.remove(event, comment.id)" class="button button-positive">
              <i class="icon ion-ios-trash"></i>
              </button>
              </div>
            
            </ion-item>
          </ion-list>
        </div>
      </ion-item>
    </ion-list>
  </ion-content>
</div>

person AWolf    schedule 26.03.2016

Вы также можете использовать параметр запроса ?deep=true, который выводит всю коллекцию в случае одного ко многим.

В вашем примере /1/objects/event/1?deep=true вернет все комментарии для события с id=1.

var id = $stateParams.id;
var useDeep = true;
EventService.getEvent(id, useDeep).then(function(response){
  $scope.event = response.data;
  $scope.comments = response.data.comments;
});
person Itay    schedule 26.03.2016