how do I take value from this $scope - angularjs

so I have this code in my chatting application, its for send message to the partner.
$scope.messages = {
from : $scope.datauser['data']['_id'],
fromname : $scope.datauser['data']['nama'],
to : $scope.tmpuserid,
message : $scope.tmp['sendmessage'],
time : moment()
};
I want to add text-to-speech features in my application, the question is how I take the value from $scope.messages but just the message because if I just write $scope.messages, TTS will read all data from from until time

Not sure exactly what you want, but it would be something like:
<div ng-repeat="message in messages">
<p>{{message.message}}</p>
</div>
EDIT: This answer is for iterating through an array of messages.
If it were just one messages object it would be:
<p>{{messages.message}}</p>

Maybe I'm missing something in your question, but if all you want to extract just the message from the messages $scope object you would use JS object dot notation e.g.
var justMessage = $scope.messages.message;
// justMessage = $scope.tmp['send message'];
// OR parse an array
var myPartnerMessages = [];
angular.forEach($scope.messages, function(msg, key) {
this.push(msg.message);
}, myPartnerMessages);

You can get the value from $scope as follows:
View.html
<div ng repeat="item in messages">
<div>{{item.message}}</div>
</div>

You just call the property as $scope.messages.message. Or since you already had it on another scope variable, you can call it as $scope.tmp['sendmessage'].
If you are trying to access from the HTML side, you would use it as this:
<p>{{messages.message}}</p>
Not exactly sure if this is what you need from reading your question, though.

if it is a single object not an array if is an array you should use ng-repeat
On js end you can get it by
$scope.messages.message
On html end you can get it by
{{messages.message}}

Related

Cannot read property 'includes' of undefined when trying to aply a filter based on a user's input

Im trying to aplly tis simple filter ased on a query of a list that with each input the list will narrow the possibilities
HTML:
<mat-form-field>
<mat-label>Search for users</mat-label>
<input #query type="text" matInput placeholder="search" (keyup)="filter(query.value)">
</mat-form-field>
<div *ngIf="filteredUsers">
And the function:
filter(query){
this.filteredUsers= query?
this.users.filter(user=>user.username.includes(query)):
this.users;
}
<ul *ngFor="let u of filteredUsers">
<li>
{{u.username}}
</li>
</ul>
</div>
The error I get as I input a character id that filter is undefined, but since both arrays fileterdUsers and Users are populated, I can't understand why this error is beig thrown...Any ideas?
EDIT: the ngOninit:
ngOnInit(): void {
this.dataService.getUsers()
.pipe(first())
.subscribe(users=>{
this.filteredUsers=this.users=users;
console.log(users, this.filteredUsers) -> i get the data
})
}
Edit 2 :
EDIT
filter(query){
console.log(this.users)
this.filteredUsers= query?
this.users.filter(user=>user.username.includes(query)):
this.users;
console.log(this.users)
}
Like this I don't see any logs...
EDIT 3: snapshot
Ok, maybe I have an idea of whats going on. The first elements of my ngFor are empty as you can see in the picture. Is this the reason for Angular's complaint? (your last fix didn't solve the issue as well)
If console.log doesnt log your array, it means its empty at the time filter(query) is being called. And I just noticed the way you are assigning the array isnt really what you want since arrays work by reference.
ngOnInit(): void {
this.dataService.getUsers()
.pipe(first())
.subscribe(users=>{
this.filteredUsers=users;
this.users=users; //just to be sure
console.log(users, this.filteredUsers) -> i get the data
})
}
filter returns an array so I guess you want to assign that to the filteredUser. I removed the code that made no sense.
filter(query){
console.log(this.users)
this.filteredUsers = query ? this.users.filter(user=> user.username && user.username.includes(query)): this.users
console.log(this.filteredUsers)
}
Whith the help and envolvment of #ukn I found the solution: the first elements of the array - seen on pic - , in this case users, were empty, so the solution was deleting those elements. The filter function is now working properly, giving me the names as I input a single char. The list gets updated trying to match the chars I input.

how to retrieve data nested in two collections from firebase with angular

I'm new in Angular - Firebase development, and I am having problems to understand how to retrieve data nested in two collections.
I have a collection named "Orders", which includes a field call "auth", which is the user ID, and I have another collection that is the "User Profile", wich it's $id is the value of "auth". Inside the User Profile I have a field named roomNumber, and it's content I that I want to retrieve every time I read, in ng-repeat of the Orders.
In my view I was trying to do something like this :
<tr ng-repeat="item in items | filter: searchKeyword ">
<td align="left">{{item.$id}} - {{roomNumber(item.$id)}}</td></tr>
roomNumber is a function in my controller
$scope.roomNumber = function(id) {
var rootRef = new Firebase("https://xxxx-fire-yyyy.firebaseio.com/userProfile"+ '/' + id);
$scope.userdet = $firebaseArray(rootRef);
rootRef.on("value", function(rootSnapshot) {
var key = rootSnapshot.key();
var childKey = rootSnapshot.child("room").val();
console.log("room ", childKey)
});
return childKey
}
When I run this code and see results in my js console, strange things happend:
1. It repeat a lot of times
2. I can never get the childKey value
I have been reading Firebase documentation, but really I do not understand how to do this "silly" thing, does anybody give me a tip of how to do it?
When you bind a function to the $scope and call it within the html it expects to get an answer back right away when called. So when you query firebase and it takes its sweet time getting you back an answer, angularjs has already gotten an answer of undefined from the function.
So what is happening is that you are registering a callback when you provide the function to rootRef.on and then right after you register the callback you are returning the value of childKey. Unfortunately, childKey only gets set by the callback function (which firebase hasn't executed yet). Therefore angularjs gets an answer of undefined from your roomNumber function.
In order to make this work, you are going to have to get the room numbers beforehand and then probably add them to each of your items in $scope.items then use
<td align="left">{{item.$id}} - {{item.room}}</td></tr>
instead of
<td align="left">{{item.$id}} - {{roomNumber(item.$id)}}</td></tr>
To load all the room numbers you could call some function like this one after $scope.items has loaded
for (var i = 0; i < $scope.items.length; i++) {
var rootRef = new Firebase("https://xxxx-fire-yyyy.firebaseio.com/userProfile"+ '/' + $scope.items[i].$id);
$scope.userdet = $firebaseArray(rootRef);
rootRef.on("value", function(rootSnapshot) {
var key = rootSnapshot.key();
var childKey = rootSnapshot.val().room;
$scope.items[i].room = childKey;
});
}
It would change each of the items to have a reference to the room. Unfortunately, that list wouldn't update as the data updates, so the better solution would be to do that same query in whatever function was getting your items from the server and add the room to each item as it was being added to the items list.
To fix the issue with childKey not reading you need to use this:
var childKey = rootSnapshot.val().room;
instead of this:
var childKey = rootSnapshot.child("room").val();
console.log("room ", childKey)
Reference: https://www.firebase.com/docs/web/guide/retrieving-data.html

Strange bug with ng-repeat and filter

I'm using NodeJS, ANgularJS, and MongoDB with mongoose
Here is my model :
var PostSchema = new mongoose.Schema({
nomReseau : String,
corps : String,
etat : String,
section : String
});
I got a function that change the attribute etat:
$scope.passer = function(index){
var post = $scope.posts[index];
post.etat = "enCours";
Posts.update({id: post._id}, post);
$scope.editing[index] = false;
}
I'm using a ng-repeat for show object in my database :
<ul>
<li ng-repeat="post in posts ">
<p>
<a ng-show="!editing[$index]" href="#/{{post._id}}">{{post.corps}}</a>
</p>
<button ng-show="!editing[$index]" ng-click="passer($index)">Passer</button>
</li>
</ul>
I can see all post in my database and when I click on the button this works perfectly the attribute etat change and all is fine.
But when I add a filter in the ng-repeat like this :
<li ng-repeat="post in posts | filter:{ etat:'aTraiter'} ">
The filter works great I have all post with the attribute etat:'aTraiter'
But if I click on my previous button and change the attribute etat nothing change and I try with other functions they all work wihout the filter but when I put it nothing work.
The problem is that $index will change if less data is shown (because you're filtering). you could use directly post variable
ng-click="passer(post)"
and your function should be something like
$scope.passer = function(post){
post.etat = "enCours";
Posts.update({id: post._id}, post);
var index = $scope.posts.findIndex(function(p) { /* comparison to get original index */ }); /* keep in mind findIndex is not supported on IE, you might want to use filter or for loop instead) */
$scope.editing[index] = false;
}
you could handle editing in the post variable directly. So in your passer function you can do this
post.editing = false;
and in your view
ng-show="!post.editing"
this way you won't use $index and you will prevent all issues with being updated by filters
There are bugs in AngularJS v1.4 where in certain situations the ng-repeat breaks. I upgraded to v1.6 and it went away.
Do you have any controllers/services that access $scope.editing? If so, you might be setting the $scope.editing[$index] equal a previous state where it wasn't equal to false. You may also want to consider that you are assuming $scope.editing[$index] is going to be a boolean. if it has any other type such as string or number then it will evaluate to true.
Otherwise none of your results have the attribute etat equal to 'aTraiter' so they aren't showing. Have you verified that any of them actually do have etat equal to 'aTraiter'. You might be changing that value somewhere else. Possibly from the Passer function

meteor angular collection find method not working

I'm trying to optimize my angular/meteor code. I have a collection
Customers = new Mongo.Collection("Customers");
and the way I was displaying them was:
ng-repeat="customer in customerController.customers | filter: {customerStore: myStore} ">
and in my CustomerController
this.customers = $meteor.collection(customers);
This approach (while it works) is now starting to take up a lot of memory on the client's server as they are adding more and more stores.
So I tried to filter server side before sending information to the client.
NEW CODE:
collection code is the same
Customers = new Mongo.Collection("Customers");
ng-repeat code is different
ng-repeat="customer in customerController.getCustomers(myStore) ">
and my controller now has this method:
this.getCustomers = function(findByStore){
return Customers.find({customerStore.$ : findByStore});
}
The problem with this is that it returns a new collection each time, so angular sees it as a different object and tries to re-render the page.
https://docs.angularjs.org/error/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:21,%22oldVal%22:19%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:23,%22oldVal%22:21%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:25,%22oldVal%22:23%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:27,%22oldVal%22:25%7D%5D,%5B%7B%22msg%22:%22fn:%20regularInterceptedExpression%22,%22newVal%22:29,%22oldVal%22:27%7D%5D%5D
One common mistake is binding to a function which generates a new array every time it is called.
Someone suggested i try
return $meteor.collection(Customers.find({'customerStore.$' : findByStore}));
but then I get the error
TypeError: The first argument of $meteorCollection must be a function or a have a find function property.

How to use ng-repeat for dictionaries in AngularJs?

I know that we can easily use ng-repeat for json objects or arrays like:
<div ng-repeat="user in users"></div>
but how can we use the ng-repeat for dictionaries, for example:
var users = null;
users["182982"] = "{...json-object...}";
users["198784"] = "{...json-object...}";
users["119827"] = "{...json-object...}";
I want to use that with users dictionary:
<div ng-repeat="user in users"></div>
Is it possible?. If yes, how can I do it in AngularJs?
Example for my question:
In C# we define dictionaries like:
Dictionary<key,value> dict = new Dictionary<key,value>();
//and then we can search for values, without knowing the keys
foreach(var val in dict.Values)
{
}
Is there a build-in function that returns the values from a dictionary like in c#?
You can use
<li ng-repeat="(name, age) in items">{{name}}: {{age}}</li>
See ngRepeat documentation. Example: http://jsfiddle.net/WRtqV/1/
I would also like to mention a new functionality of AngularJS ng-repeat, namely, special repeat start and end points. That functionality was added in order to repeat a series of HTML elements instead of just a single parent HTML element.
In order to use repeater start and end points you have to define them by using ng-repeat-start and ng-repeat-end directives respectively.
The ng-repeat-start directive works very similar to ng-repeat directive. The difference is that is will repeat all the HTML elements (including the tag it's defined on) up to the ending HTML tag where ng-repeat-end is placed (including the tag with ng-repeat-end).
Sample code (from a controller):
// ...
$scope.users = {};
$scope.users["182982"] = {name:"John", age: 30};
$scope.users["198784"] = {name:"Antonio", age: 32};
$scope.users["119827"] = {name:"Stephan", age: 18};
// ...
Sample HTML template:
<div ng-repeat-start="(id, user) in users">
==== User details ====
</div>
<div>
<span>{{$index+1}}. </span>
<strong>{{id}} </strong>
<span class="name">{{user.name}} </span>
<span class="age">({{user.age}})</span>
</div>
<div ng-if="!$first">
<img src="/some_image.jpg" alt="some img" title="some img" />
</div>
<div ng-repeat-end>
======================
</div>
Output would look similar to the following (depending on HTML styling):
==== User details ====
1. 119827 Stephan (18)
======================
==== User details ====
2. 182982 John (30)
[sample image goes here]
======================
==== User details ====
3. 198784 Antonio (32)
[sample image goes here]
======================
As you can see, ng-repeat-start repeats all HTML elements (including the element with ng-repeat-start). All ng-repeat special properties (in this case $first and $index) also work as expected.
JavaScript developers tend to refer to the above data-structure as either an object or hash instead of a Dictionary.
Your syntax above is wrong as you are initializing the users object as null. I presume this is a typo, as the code should read:
// Initialize users as a new hash.
var users = {};
users["182982"] = "...";
To retrieve all the values from a hash, you need to iterate over it using a for loop:
function getValues (hash) {
var values = [];
for (var key in hash) {
// Ensure that the `key` is actually a member of the hash and not
// a member of the `prototype`.
// see: http://javascript.crockford.com/code.html#for%20statement
if (hash.hasOwnProperty(key)) {
values.push(key);
}
}
return values;
};
If you plan on doing a lot of work with data-structures in JavaScript then the underscore.js library is definitely worth a look. Underscore comes with a values method which will perform the above task for you:
var values = _.values(users);
I don't use Angular myself, but I'm pretty sure there will be a convenience method build in for iterating over a hash's values (ah, there we go, Artem Andreev provides the answer above :))
In Angular 7, the following simple example would work (assuming dictionary is in a variable called d):
my.component.ts:
keys: string[] = []; // declaration of class member 'keys'
// component code ...
this.keys = Object.keys(d);
my.component.html: (will display list of key:value pairs)
<ul *ngFor="let key of keys">
{{key}}: {{d[key]}}
</ul>

Resources