Angular - Assign new value to FirebaseListObservable - javascript

Not sure how this is suppose to be done.
filter is a Firebase list observable.
filter: FirebaseListObservable<UserModel[]>;
This is the query. It gets all users with a specific occupation.
this.filter = this.db.list('occupationsUsers/' + occupation + '/users');
Then I use an <md-list> which works. It displays all users with occupation.
<md-list>
<md-list-item *ngFor="let user of filter | async" [value]="user.email">{{user.email}}
<button md-button [mdMenuTriggerFor]="menu">Menu</button>
<md-menu #menu="mdMenu">
<button md-menu-item (click)="removeUserFromFilterList(user.email)">Delete</button>
</md-menu>
</md-list-item>
</md-list>
removeUserFromFilterList
removeUserFromFilterList(userEmail: string) {
var index = this.eventForm['guests'].indexOf(userEmail);
this.filter = this.eventForm['guests'].splice(index, 1);
}
The error:
ERROR Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'
at invalidPipeArgumentError
How do I populate this.filter with the new updated user list and keep it working with the firebase query?

this.filter as you mention , is a FirebaseListObservable. and as i understand , this.eventForm is just an array(and not like this.filter).
i would recommend you to use one of the following methods:
this.filter.update('key-of-some-data', { object to remove });
or
this.filter.remove('key-of-some-data');
you can read more about that on
click here

Related

How to populate data from backend in dropdownlist and select the value in Angular?

I hava Angular 8 application and I am using material.
What I want to archieve is that data from the backend will be populated in a dropdownlist.
The code of the api call looks like this:
returnQrCodes$ : Observable<QRCodeDefinitionSelectOptionApi[]>;
api call:
getQrCodes(){
this.returnQrCodes$ = this.qrDefinitonService.getDefinitionForSelection().subscribe(result => {
console.log(result);
})
}
and the template looks like this:
<div
class="search-select searchoptions" *ngIf="selectedSearch && hasOtherOptions(selectedSearch)">
<mat-select placeholder="Opties" name="option" [(ngModel)] = "selectedValueOptie" >
<mat-option *ngFor="let option of returnQrCodes$ | async " [value]="option.value" >
{{ option.qrCode }}
</mat-option>
</mat-select>
</div>
But I get the following error:
Type 'Subscription' is missing the following properties from type 'Observable<QRCodeDefinitionSelectOptionApi[]>': _isScalar, source, operator, lift, and 6 more.ts(2740)
on this line:
this.returnQrCodes$
Thank you
So I have a other api call who filters the values:
like this:
filterByQrCodes() {
this.participantService
.filterParticipantsByQRCode(1, this.selectedValue as any , moment(this.startDate).format('YYYY MM D'), 'testQrJoost176')
.subscribe(filterByQrcode => {
console.log(filterByQrcode);
console.log(this.selectedValue as any);
});
}
So the dropdown values from the backend has to filtered with this api call
So how now use this api call:
getQrCodes(){
this.returnQrCodes$ = this.qrDefinitonService.getDefinitionForSelection().pipe(
tap(console.log)
)
}
with this hard coded value: testQrJoost176 so that a user can select a value from the dropdownlist
Use
getQrCodes(){
this.returnQrCodes$ = this.qrDefinitonService.getDefinitionForSelection()
}
if you need to console.log also use (side effect):
getQrCodes(){
this.returnQrCodes$ = this.qrDefinitonService.getDefinitionForSelection().pipe(
tap(console.log)
)
}

How to maintain a constant scope in angular?

I have an angular service that fetch contacts data from the database, I then use these data so that the user can add one contact or more to a deal, so there is a many to many relationship between the deal and contact, the selected data are displayed in a grid (syncfusion grid).
I need to have a constant list of the data retrieved from database, and a varible containing the selected contacts that I pass to the syncfusion grid, when the user add from the dropdown I add this contact to the grid and remove it from the dropdown list, and if I deleted it from the grid I return it back to the drop down list, so here's my code:
this service get the contact list:
var contactsListDB = [];
contactService.getAll().then(function (contacts) {
contactsListDB = contacts.data;
$scope.contactsList = contactsListDB; // the scope used in the select input in the HTML
});
the method that add contact:
$scope.addContact = function (contact) {
var contactJson = JSON.parse(contact);
$scope.dealContacts.push(contactJson);
var index = $scope.contactsList.findIndex(x => x.id == contactJson.id);
SyncFusionDealContact($scope.dealContacts);
$scope.contactsList.splice(index, 1);
}
this function is invoked in HTML:
<ng-form name="ContactForm">
<md-input-container>
<label>{{"Contact" | translate}}</label>
<md-select ng-model="contact">
<md-option value="{{null}}">-- {{"selectContact" | translate}} --</md-option>
<md-option ng-repeat="contact in contactsList" value="{{contact}}">{{contact.name}}</md-option>
</md-select>
</md-input-container>
<md-input-container>
<div>
<button class="btn btn-primary" type="submit" ng-disabled="!ContactForm.$valid" ng-click="addContact(contact)" aria-label="submit">{{'add' | translate}}</button>
</div>
</md-input-container>
<div id="GridDealContacts">
<script id="columnTemplateContacts" type="text/x-jsrender">
<a class="btn btn-danger btn-xs contactDelete" data-id="{{:id}}" ng-click="DeleteContact{{:id}}"><i class="fa fa-trash-o "></i></a>
<!--add delete button-->
</script>
</div>
</ng-form>
When the page is loaded I check if the object is being edited and then I exclude the existing contacts from the list comming from contacts table:
$scope.dealContacts = deal.contacts;
SyncFusionDealContact($scope.dealContacts);
execludeContacts()
execludeContacts function:
function execludeContacts() {
var exIds = [];
if ($scope.dealContacts.length > 0) {
exIds = $scope.dealContacts.map(x=> x.id)
}
var conts = contactsListDB;
conts.forEach(function (item, index) {
if (exIds.includes(item.id)) {
conts.splice(index, 1);
}
})
$scope.contactsList = conts;
}
this function handles delete action:
$scope.DeleteContact = function (id, index) {
if (id <= 0) {
$scope.dealContacts.splice(index, 1)
SyncFusionDealContact($scope.dealContacts);
}
else {
if (confirm("Are You Sure?")) {
dealService.deleteContact(id, $routeParams.id).then(function (success) {
if (success.data.isSuccess) {
SyncFusionDealContact($scope.dealContacts);
var one = contactsListDB.filter(x => x.id == id)[0];
$scope.contactsList.push(one);
$scope.dealContacts.splice(index, 1);
}
else {
alert('Cannot delete');
}
SyncFusionDealContact($scope.dealContacts);
});
}
}
}
In the code above I tried to save a copy of the contacts list in a variable that can't be changed contactsListDB, so that when a record is deleted from the grid I can get it back from this array to add it in the drop-down list again, but what happens is that the array is changed:
Screenshot:
I'm not sure of what you're asking, but I think you want to 'save' the data somewhere? If that's the case, take a look at using a factory or service. I prefer using a factory because of its simplicity.
From the short period I've worked with Angular, I know that a factory will always stay alive (even while switching views in SPA) until you refresh the page.
In a simple example, the factory will hold a list of the contacts, and have several functions like your addContact and deleteContact. This makes your code less cluttered and you just have to call the factory and its functions in your code.
I currently can't give a specific example (as I prefer using my own factories and its usage), but here you can find a comparison between factory and service and how to use them.
If I misunderstood your question, please do tell. :D

Storing strings in array as user selects checkbox

I just started using angularJS and am trying to learn how to insert strings in array when user clicks checkbox and later access these values.
This is what I have so far:
<md-button class="toolbar-button" ng-click="removePlan()">
<md-icon>delete</md-icon>
</md-button>
<md-list-item ng-repeat="plan in plans">
<md-checkbox ng-model="plansSelected[plan._id]"> </md-checkbox>
</md-list-item>
apps.js
$scope.plansSelected = []
$scope.removePlan = function () {
for (var plan in $scope.plansSelected) {
if ($scope.plansSelected[plan] === true) {
projectResource.removePlan(plan).then(function (data) {
if (data.success) {
$scope.plans.push(data.plan)
}
})
}
}
}
projectResource.js
resource.removePlan = function (planId) {
return $http.delete(getPlanUrl(planId)).then(processResponse, processError)
}
function getPlansUrl () {
return getProjectUrl() + '/plans'
}
function getPlanUrl () {
return getPlansUrl() + '/' + $route.current.params.planId
}
In debugger this is how my array looks like:
$scope.plansSelected: Array[0]
57bd40128a58022800887d80:false
57bd40328a58022800887d88:false
57cc2bcbb452140500b0334a:false
I am checking if user removed selection from the checkbox and if the value is true then take that plan._id and pass in the loop to removePlan function.
Does anyone see what I am doing wrong, because this is not working.
Please be more specific what "this is not working" means - it's hard for us to detect that without being able to run it.
I can see that your use of $scope.plansSelected as an empty array is wrong. I would dispense with that and do it like this:
<md-list-item ng-repeat="plan in plans track by $index">
{{plan.name}} <md-checkbox ng-model="plans[$index].selected"> </md-checkbox>
</md-list-item>
This basically adds a 'selected' attribute to your plans array, and make it easier for you to iterate over the plans array and pull out the ones you want.

Using $http.get in ng-repeat causes multiple errors

I have a function what returns an array of items by group Id. Here it is:
var getChoices = function (groupId) {
var request = $http.get(_baseUrl + 'choice', { params: { choiceGroupId: groupId } });
return request.then(function(result) {
if (resources.ok(result)) {
return result.data.items;
}
}, function(error) {
});
}
It works fine when I bind it to button, but when I try to make ng-repeat over this function results I have multiple errors in browser console.
<md-list>
<md-list-item ng-repeat="choice in getChoices(choiceGroupId)">
{{choice}}
</md-list-item>
</md-list>
I've also tries this, but result is the same.
<md-list ng-init="choices = {{getChoices(choiceGroupId)}}">
<md-list-item ng-repeat="choice in choices">
{{choice}}
</md-list-item>
</md-list>
I've seen answers to questions like this, but there people suggested to make request in the controller, then fill the array with data, and iterate over array values, but this doesn't suit my case because I need that choiceGroupId from the UI side.
It seems like browser tries to evaluate get request on each tick and something like overflow happens. How can I handle this to call 'get' once and then iterate over returned result?
Check If your choices variable has duplication of value , If yes than try below code
<md-list>
<md-list-item ng-repeat="choice in choices track by $index">
{{choice}}
</md-list-item>
</md-list>
var getChoices = function (groupId) {
var request = $http.get(_baseUrl + 'choice', { params: { choiceGroupId: groupId } });
return request.then(function(result) {
if (resources.ok(result)) {
$scope.choices= result.data.items;
}
}, function(error) {
});
}

Duplicate in ng-repeat error

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.

Categories