Using text input as filter option - angularjs

I struggle with the usage of the filter. I have an input field that i want to use as a filter option.
The array looks like this:
$scope.Examples=[
{
name:'Dolly',
place:'roof',
description:'Dolly is a friend of Mike.'
},
{
name:'Mike',
place:'cellar',
decription:'Mike doesn't like the roof.'
},];
$scope.Search="";
The Input:
<input ng-model="Search"
type="text"
placeholder="type something here">
And the ng-repeat:
<tr ng-repeat="something in Examples |filter:Search">
{{something.name}}
</tr>
Now, if i type in "Dolly", he shows me Dolly quite as planned. But if i type in "Mike" the output is Dolly and Mike, because i used the word Mike in the description for Dolly. The same for typing in "roof".
I tried to use
<ng-repeat="something in Examples |filter:{name:'Search'}">
but in that case it simply don't work and there is no output. What i want to do is restrict the filter to 'name' only. Maybe someone have a suggestion how i could make it work.
I'm thankful for every advice.

If you write {name:'Search'} instead of {name:Search}, it means that you keep any string which contains the 'Search' string
Try this :
<ng-repeat="something in Examples |filter:{name:Search}">

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.

Chaining an element using css containing text and accessing an associated field

I need to access the input field in the below html. The way the page is setup I need to chain using the 'Address Line 1' text and then sending text to the input field. The input field id changes and so doesn't the layout of the fields depending on user preference. I am struggling. If you need some more information feel free to ask I did not want to overload with too much information.
<td class="labelCol requiredInput">
<label for="00N36000000xina"><span class="assistiveText">*</span>Address Line 1</label>
</td>
<td class="dataCol col02">
<div class="requiredInput">
<div class="requiredBlock"></div>
<input id="00N36000000xina" maxlength="255" name="00N36000000xina" size="20" tabindex="4" type="text">
</div>
</td>
I have accessed like this:
element(by.css('div.pbSubsection:nth-child(3) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2) > input'))
However depending on where the user puts the fields it can move around. So what I was hoping was to be able to access the label\ and use that to pinpoint its input field.
I don't know protractor but I cobbled together some code that hopefully will work or be close and I'll give you the thought process and some info and hopefully you can use it to fix my code, if needed, and solve the problem.
Start by finding an element by XPath, "//label[text()='Address Line 1']". This searches for a LABEL tag that contains "Address Line 1". Once you find that element, get the label attribute. From your HTML, this label is the id for the INPUT element you want. Now use the id to find the element and do with it what you want.
id = element(by.xpath("//label[text()='Address Line 1']")).getAttribute("label")
input = element(by.id(id))
input.sendkeys("some text")
Haven't tested this myself, but you could try something like this:
// $ is shorthand for element(by.css())
$('div.assistiveText').getAttribute('for').then(function (val) {
// locate the <input> by the value of the attribute on <label>
element(by.id(val)).sendKeys('abc'); // replace sendKeys with your intended function
});
Or if that first locator on the label isn't specific enough, swap out $('div.assistiveText') for element(by.cssContainingText('Address Line 1'))
I tried it for other attributes (I don't have a for attribute anywhere in my app) and it seemed to work for me.
Try this:
List<WebElement> elementList = driver.findElements(By.cssSelector("tbody > tr"));
for (WebElement element : elementList) {
if(element.findElement(By.cssSelector("td.labelCol > label")).getText().equalsIgnoreCase("Address Line 1")) {
element.findElement(By.cssSelector("input[type='text']")).sendKeys("textToInput");
}
}

Angularjs Binding Dropdown using ng-options

I have looked at the angular documentation https://docs.angularjs.org/api/ng/directive/ngOptions but still can't figure this one out.
I have a list of sexes that get bound to a select like this:
$scope.sexes = jQuery.grep(formData, function(a) {
return (a.category == "Sex");
});
the JSON for the sex list looks like this:
2: Object
alternateCode: null
category: "Sex"
code1: "F"
codeID: 60002
description: "Female"
lastModifiedBy: ""
lastModifiedDate: "1900-01-01T00:00:00"
subCategory: null
The member object that should make the select choice has a property on it sex:M. The problem is when I try to bind the select it will populate the list correctly but will not select the option I need:
<select name="sex" id="sex" class="form-control"
ng-model="editableMember.sex"
ng-options="s.sex as s.description for s in sexes track by s.code1 "></select>
Any help would be greatly appreciated
Perhaps you missed this part of the documentation:
Do not use select as and track by in the same expression. They are not designed to work together.
The ng-model value will be the result of either the select or track by expression. The following code for ng-options should work:
ng-options="s.code1 as s.description for s in sexes"

How to display xml2json data

I am using xml2json to translate a xml file from medline. I am stuck on using ng-repeat to display the information I need. I need to display the title,url and see-reference. When i have one health-topic in the xml file The title and url display fine. When I add more health-topics it does not work. any help is appreciated, thanks
plunkr
<table>
<tr ng-repeat="topic in topics">
<td>{{topic._title}}</td>
<td>{{topic._url}}</td>
<td>{{topic.see-reference}}</td>
</tr>
</table>
<pre>{{topics | json}}</pre>
The structure of your XML is like this:
<health-topics total="1909" date-generated="01/03/2015 02:30:35">
<health-topic title="Abdominal Pain">
</health-topic>
<health-topic title="Abdominal Pain">
</health-topic>
<health-topic title="Abdominal Pain">
</health-topic>
xml2json creates an object for every element. The properties of the object are the element's attributes (starting with an underscore) and the child elements. In your case:
//health-topics
{
_total: "1909",
_date-generated: "01/03/2015 02:30:35",
health-topic: [
{
_title: Abdominal Pain"
...
health-topic is an array containing the topics. If you have a single topic wrapped with health-topics it would be:
//health-topics
{
_total: "1909",
_date-generated: "01/03/2015 02:30:35",
health-topic: {
_title: Abdominal Pain"
...
health-topic is now an object. But maybe a single topic wouldn't even be wrapped with a health-topics element. That's something only you know.
All in all the data structure is different depending on the number of topics. You would need to check and adapt to that. The code working for multiple topics would be
$scope.topics = $scope.dom['health-topics']['health-topic']

Nesting angular binding in ng-repeat

Just curious if this is something that is currently possible in Angular, or if I have to write my own directive.
I'm attempting to dynamically create input tags for each property on any object. To accomplish this, I am inspecting the object in javascript and creating an array that contains the objects property names mapped to the corresponding input "type".
Ex.
var fields = []
for (var name in myObject) {
if (!myObject.hasOwnProperty(name)) continue;
fields.push({ 'name': name, 'inputType': typeToInputType(myObject[name]) });
}
$scope.fields = fields;
Then in my markup I go ahead and do the following:
<label for="{{f.name}}" ng-repeat="f in fields">
{{f.name}}: <input name="{{f.name}}" ng-model="myObject.{{f.name}}" type="{{f.inputType}}" />
</label>
Everything works great except when we get to this attribute:
ng-model="myObject.{{f.name}}"
That is causing serious problems. The idea behind it is that I have a
$scope.myObject
and when people type stuff into the inputs, for example the "Name" input, then it should be equivalent to:
$scope.myObject.Name = "I typed stuff";

Resources