Как добавить id объекта в другой объект с 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
}
})
3 ответа
Лучше перенести логику получения всех комментариев определенного события из бэкэнда, чем получать все с сервера и фильтровать его во внешнем интерфейсе. Вы можете сделать звонок, например:
http://mysite/getComments?eventId=2533213
И в вашей схеме комментариев (для БД) у вас может быть одно поле в качестве eventId. Затем вы можете получить все комментарии, имеющие идентификатор события, предоставленный в вызове, из БД и вернуться в свое приложение в ответ.
В front-end вы можете сделать:
контроллер:
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
};
Вы также можете использовать параметр запроса? 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;
});
Вы также можете создать запрос на панели инструментов 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 - это идентификатор события)
Моя модель БД для демонстрации выглядит следующим образом:
И модель БД 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.
Угловой код может быть немного изменен, но он работает. Если что-то не так, пожалуйста, дайте мне знать, потому что это мой первый пример с 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>