Duplicate in ng-repeat error - javascript

Hello for some reason it says as a error:
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: mes in messagess, Duplicate key: string:f, Duplicate value: f
But i dont understand why, i personally dont see any duplicates...
Here is my Cloud9 File to see the code and make changes...
Here is my Chat.html:
<h1 style = "text-align:center; position:relative; left:-80px"> Universal Chat </h1>
<div id = "rectangle" >
<ul id="example-messages" class="example-chat-messages">
<li ng-repeat = "mes in messagess">
{{mes}}
</li>
</ul>
</div>
<textarea class="form-control" id="chatbox" rows="1" ng-model = "textValue">
</textarea>
<a class="btn right" id = "submitButton" ng-click = "submit()">
<span class="left title">Submit Comment</span>
<span class="right icon icon-comment"><span class="slant-right"></span></span>
</a>
And my chatController.js:
app.controller('chatController', ["$scope", 'AuthService', "Auth", "Ref", "$rootScope", "$firebaseArray", "$firebaseObject",
function($scope, AuthService, Auth, Ref, $rootScope, $firebaseArray, $firebaseObject) {
var postsArray = {}
console.log(AuthService.User.email) //Gives me correct Email
console.log(AuthService.User.password) //Gives me correct password
console.log(AuthService.User.uid) //Gives me correct uid
console.log(AuthService.User.username) //Gives me correct username
some = $firebaseArray(Ref.child("Posts").child(AuthService.User.username));
console.log((some))
var postsFirebase = $firebaseObject(Ref)
var username = AuthService.User.username
$scope.messagess = {}
$scope.submit = function() {
if (!($scope.textValue)) {
}
else {
some.$add({
Posts: $scope.textValue
}).then(function(authData) {
console.log(authData.path)
Ref.child("Posts").child(username).child(authData.path.o[2]).on("value", function(snapshot) {
console.log(snapshot.val().Posts)
$scope.messagess.push(snapshot.val().Posts)
snapshot.val().Posts
}, function(errorObject) {
console.log("The read failed: " + errorObject.code);
});
}).catch(function(errorObject){
alert("See the console for more details")
console.error(errorObject.code)
})
}
}
}
])
SnapShot.val is like the current post you submitted in my firebase here:
This is not a duplicate. Those methods from other places didnt work..

The duplicate error says its f duplicated, so I suppose the messages is a string, not an array. What you are trying to do is to display every message. But now, you are iterating over the message itself, that is:
<li ng-repeat="mes in 'message'">
Which takes m for the first item, e for second, s fot the third. And, as you may suppose, it will throws the error when it notices the next (duplicated) s.
You should iterate over array of messages, i.e.:
<li ng-repeat="mes in ['message']">
Which will display them correctly. Please review what is saved to the scope in this line:
$scope.messagess = snapshot.val().Posts
It should be an array.
However, please note that after fixing it you should still use the track by as posting the same message twice will tirgger the error again.
<li ng-repeat="mes in messages track by $index">
Related: Angular ng-repeat Error "Duplicates in a repeater are not allowed."]
If you still have the problem, please try to create Minimal, Complete, and Verifiable example so we can help.
UPDATE:
Based on the screen of data structure you provided (the Posts is string as I supposed), you should change the scope assignment to:
$scope.messagess = snapshot.val()
and then, in the view, read all values, i.e.
<li ng-repeat="mes in messages">{{ mes.Posts }}</li>
However, I find this structure (and naming) weird.

Related

Angular.js - Slicing a json request according to user input

I am a beginner at Angular.js and am currently going through the tutorial. I decided to try making the number of phones displayed changeable by the user. In my controller:
function PhoneListController($http) {
var self = this;
self.orderProp = 'age';
$http.get('phones/phones.json').then(function(response) {
self.phones = response.data.slice(0, self.displayNum);
});
}
PhoneListController.$inject = ['$http']; //services to inject for each parameter in PhoneListController
I slice the response data that I get from the server according to the displayNum input by the user. I'm sure that displayNum is updated in the model, however it doesn't slice the json as I expected it to. Is the http request only made once at the start?
The relevant section of my template:
<p>
Number of phones displayed:
<input ng-model="$ctrl.displayNum" />
</p>
...
<ul class="phones">
<li ng-repeat="phone in $ctrl.phones | filter:$ctrl.query | orderBy:$ctrl.orderProp">
<span>{{phone.name}}</span>
<p>{{phone.snippet}}</p>
</li>
</ul>
<p>display num: {{$ctrl.displayNum}}</p>
The display num: {{$ctrl.displayNum}} at bottom updates according to the number input in <input ng-model="$ctrl.displayNum" />, but the list does not change size. If I hardcode a value in for self.displayNum in the controller the list is sliced correctly when I refresh the page, but changing the value in the input does nothing to the list.
As mentioned by #Alexander-Bolzhatov, I simply put the http request in a change function, called by ng-change in the template.
$http.get('phones/phones.json').then(function(response) {
self.phones = response.data;
});
self.change = function(){
$http.get('phones/phones.json').then(function(response) {
self.phones = response.data.slice(0, self.displayNum);
});
};
Template code:
Number of phones displayed:
<input ng-model="$ctrl.displayNum" ng-change="$ctrl.change()"/>

How can I correctly use variable variable names in ng-repeat in angular?

HTML:
<ul>
<li ng-repeat="comic in comiclist">
<span>{{ comic.title }} : {{comic.id}}</span>
<div >
<img ng-src="{{comic.thumbnail.path}}.{{comic.thumbnail.extension}}"/>
</div>
<div>
<ul>
<li ng-repeat="character in charlist + {{comic.id}}">
<span>{{character.name}}</span>
</li>
</ul>
</div>
</li>
</ul>
JS with angular
var App = angular.module('MarvelApp', []);
App.controller('MainController', function($scope,$window, $http) {
$scope.GetSeries = function(){
$http.get('http://gateway.marvel.com/v1/public/series?')
.then(function(response){
$scope.serieslist = response.data.data.results;
});
};
$scope.GetComics = function(){
$http.get('http://gateway.marvel.com/v1/public/series/' + $scope.selectedseries + '/comics?')
.then(function(response){
$scope.comiclist = response.data.data.results;
});
//comic in comiclist contains comic.id
//which needs to go to GetCharacter()
}
$scope.GetCharacter = function(comicid){
$http.get('http://gateway.marvel.com/v1/public/comics/' + comicid + '/characters')
.then(function(response){
$scope.['charlist' + comicid] = response.data.data.results;
//this list needs to be displayed in the second ng-repeat
});
};
});
I'd like to get the character list to display in the right div. How I had it set up before, (without $scope.['charlist' + comicid]) it was overriding the other ng-repeats too.
Also, whenever GetComics() gets called it does it automatically.
I don't think $scope.[] is valid syntax (unless I've been missing out on a nifty trick).
You should instead name an "associative array" under $scope something like:
$scope.charlist[comicid] = ... ;
Your ng-repeat would then look something like:
<li ng-repeat="character in charlist[comic.id]">
EDIT As mentioned in the comments, $scope.charlist must be defined before the above lines can be used. This can happen in a few ways:
Make a check before you set it: if(!$scope.charlist) $scope.charlist = [];
Define it somewhere in the controller with $scope.charlist = [];
Of course there's any number of ways you can do this, but these make these I believe make the most sense, the first of which catches invalid states i.e. if for some reason $scope.charlist is set to null it would create a new "associative array".

Mongo pull in Meteor not pulling

I've been trying to pull an array from Mongo inside of Meteor, but I can't seem to get it to work. I'm able to push to it fine. Any help would be greatly appreciated. Here's my html:
<ul class="schedule">
{{#each employee.schedule}}
<li class="schedule_item"><a class="btn listExRemove" title="Remove this name">x</a><p class="schedule_item_info">{{ . }}</p></li>
{{/each}}
</ul>
<div class="form-group form-md-line-input">
<input type="text" name="schedule" value="" class="form-control" id="schedule" placeholder="Enter the schedule" >
<label for="item">Schedule</label>
</div>
Add
Here is the javascript for pushing:
'click #add_event': function(event, template) {
var id = this._id; // Set equal to the current id
var push_it = $('#schedule').val();
Employees.update({_id:id}, {
$push: {
schedule: push_it
}
});
console.log("It's updated");
And here is me pulling:
'click .listExRemove': function(event, template) {
var id = this._id; // Set equal to the current id
var the_text = $(event.target).parent().find('.schedule_item_info').text();
Employees.update({_id: id}, {
$pull: {
schedule: the_text,
}
});
console.log(the_text);
Edit:
New values are being pushed into the collection by clicking the "#add_event" button. It then pushes the value of the "#schedule" input into the "schedule" array.
Values are trying to be removed by clicking the ".listExRemove" button. It then looks in the parent container for the ".schedule_item_info" text, and saves it in the "the_text" variable. Next it should pull "the_text" from the "schedule" array, and display "the_text" in the console.
It displays "the_text" in the console, but doesn't pull it from the collection. I'm not receiving any errors, warnings, etc. I've tried pushing into different array variations and pulling without success. I've also tried replacing "the_text" with a string I know is in the array to no avail.
It turns out since the "listExRemove" button was in an {{#each}} loop, "this._id" wasn't getting the id of the template. In order to get the id I used "template.data._id" instead.

Update unrelated field when clicking Angular checkbox

I have a list of checkboxes for people, and I need to trigger an event that will display information about each person selected in another area of the view. I am getting the event to run in my controller and updating the array of staff information. However, the view is not updated with this information. I think this is probably some kind of scope issue, but cannot find anything that works. I have tried adding a $watch, my code seems to think that is already running. I have also tried adding a directive, but nothing in there seems to make this work any better. I am very, very new to Angular and do not know where to look for help on this.
My view includes the following:
<div data-ng-controller="staffController as staffCtrl" id="providerList" class="scrollDiv">
<fieldset>
<p data-ng-repeat="person in staffCtrl.persons">
<input type="checkbox" name="selectedPersons" value="{{ physician.StaffNumber }}" data-ng-model="person.isSelected"
data-ng-checked="isSelected(person.StaffNumber)" data-ng-change="staffCtrl.toggleSelection(person.StaffNumber)" />
{{ person.LastName }}, {{ person.FirstName }}<br />
</p>
</fieldset>
</div>
<div data-ng-controller="staffController as staffCtrl">
# of items: <span data-ng-bind="staffCtrl.infoList.length"></span>
<ul>
<li data-ng-repeat="info in staffCtrl.infoList">
<span data-ng-bind="info.staffInfoItem1"></span>
</li>
</ul>
</div>
My controller includes the following:
function getStaffInfo(staffId, date) {
staffService.getStaffInfoById(staffId)
.then(success)
.catch(failed);
function success(data) {
if (!self.infoList.length > 0) {
self.infoList = [];
}
var staffItems = { staffId: staffNumber, info: data };
self.infoList.push(staffItems);
}
function failed(err) {
self.errorMessage = err;
}
}
self.toggleSelection = function toggleSelection(staffId) {
var idx = self.selectedStaff.indexOf(staffId);
// is currently selected
if (idx >= 0) {
self.selectedStaff.splice(idx, 1);
removeInfoForStaff(staffId);
} else {
self.selectedStaff.push(staffId);
getStaffInfo(staffId);
}
};
Thanks in advance!!
In the code you posted, there are two main problems. One in the template, and one in the controller logic.
Your template is the following :
<div data-ng-controller="staffController as staffCtrl" id="providerList" class="scrollDiv">
<!-- ngRepeat where you select the persons -->
</div>
<div data-ng-controller="staffController as staffCtrl">
<!-- ngRepeat where you show persons info -->
</div>
Here, you declared twice the controller, therefore, you have two instances of it. When you select the persons, you are storing the info in the data structures of the first instance. But the part of the view that displays the infos is working with other instances of the data structures, that are undefined or empty. The controller should be declared on a parent element of the two divs.
The second mistake is the following :
if (!self.infoList.length > 0) {
self.infoList = [];
}
You probably meant :
if (!self.infoList) {
self.infoList = [];
}
which could be rewrited as :
self.infoList = self.infoList || [];

Angular ng-model won't pass

I'm working on an app, and am trying to pass a string through ng-model like I do in other places. But this one always returns "undefined".
HTML:
<aside>
<p>List of objs:</p>
<ul>
<li class="objList" ng-repeat="obj in objs">
{{ obj.topic }}
<div class="appear" ng-show="hideBool2">
X
<input class="uName" ng-model="passWo" placeholder="Password">
<button class="btn btn-default" ng-click="connectTo(obj.info)">OK</button>
<p ng-bind="message"></p>
</div>
</li>
</ul>
</aside>
Controller function used:
$scope.connectTo = function(rName) {
alert($scope.rooms[rName].password + " " + $scope.passWo)
if($scope.rooms[rName].password != "") {
if($scope.rooms[rName].password == $scope.passWo) {
socket.emit("joinroom", { room: rName, pass: $scope.passWo }, function(success, errorMessage) {});
$location.path("/room/" + rName);
}else{
$scope.message = "Wrong password";
}
}else{
alert($scope.rooms[rName].password);
}
}
but the $scope.passWo always returns undefined.
Everything else works in the code.
Any help would be appreciated.
The problem is that the ng-model is assigning the value to its internal $scope. So when you call the connectTo function, it finds the $scope.connectTo in the controller scope, but the use of $scope.passWo, can't find the value, as ng-repeat creates a scope for each item.
The easiest way to overcome this (if you want to use a single scope value) is to create a container object inside the controller:
$scope.cont = { passWo: '' };
Then inside your view, use:
ng-model="cont.passWo"
This article might help you: http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html

Categories