Angular material group dropdown - How to add group name to text box - angular-material2

I have a material group dropdown designed just like the official documentation (here).
Question is : How can I display the selected item text along with group name.
ie; If I select Bulbasaur from 'Grass' group, as in the image, it should show 'Grass - Bulbasaur' instead of just 'Bulbasaur'. Any ideas?
Update: I have found a work around. Anyone fiddling around with the same issue can do this css hack in the mean time,
<mat-form-field>
<mat-select placeholder="Pokemon" [formControl]="pokemonControl">
<mat-option>-- None --</mat-option>
<mat-optgroup *ngFor="let group of pokemonGroups" [label]="group.name"
[disabled]="group.disabled">
<mat-option *ngFor="let pokemon of group.pokemon" [value]="pokemon.value">
<span style=display:none">{{group.name}} -</span>{{ pokemon.viewValue }}
</mat-option>
</mat-optgroup>
</mat-select>
</mat-form-field>

It looks like the proper way to do this is to set "custom trigger text":
See the examples for the MatSelect instead of the overview
So you would do something like this:
<mat-form-field>
<mat-select placeholder="Pokemon" [formControl]="pokemonControl">
<mat-select-trigger *ngIf="pokemonControl.value; let pokemon">
{{ pokemon.parentViewValue }} : {{ pokemon.viewValue }}
</mat-select-trigger>
<mat-option>-- None --</mat-option>
<mat-optgroup *ngFor="let group of pokemonGroups" [label]="group.name"
[disabled]="group.disabled">
<mat-option *ngFor="let pokemon of group.pokemon" [value]="pokemon">
{{pokemon.viewValue}}
</mat-option>
</mat-optgroup>
</mat-select>
</mat-form-field>
Take note of two things:
Obviously the mat-select-trigger tag... I am using the full pokemon model, you will need to add either a reference to the parent group or, like I have done, add the parent view value in each pokemon. You can do either when you actually construct the model
My [value] for the mat-option tag is pokemon instead of pokemon.value as I need the full model

Related

Xpath: Select elements based on descendants that do not have a certain attribute

I am scraping through real estate listings from a certain site that contains multiple pages.
Here, I have summarized a structure nested deep in the DOM. I want to select all list items, based on the descendants that do not have a certain attribute name like <div id="nav-ad-container">
<ul class="photo-cards photo-cards_wow photo-cards_short photo-cards_extra-attribution">
<li>..</li>
<li>..</li>
<li>
<div id="nav-ad-container" class="zsg-aspect-ratio"></div>
</li>
<li>..</li>
<li>..</li>
<li>..</li>
</ul>
However, given that the attribute and the attribute's name change in the DOM for each page.
For example:
#id = 'nav-ad-container' or #class = 'nav-ad-empty'
In general, I want to retrieve the list items that do not contain the name pattern 'nav-ad'.
Things that I've tried with no success (still selects every list item)
xpath + //li[not(contains(#class, 'nav-ad'))]
xpath + //li[not((contains(#class,'nav-ad')) or contains(#id,'nav-ad'))]
Can anyone guide me toward a solution? I feel like I'm pretty close but missing something.
filter by classname of list items or descendants:
//li[not(contains(descendant-or-self::node()/#class,'nav-ad'))]
(not tested)
Try
//li[not(descendant-or-self::node()/#class[contains(.,'nav-ad')])]

How to check angular material 2 mat-list-option is checked or not?

I want to use a mat-list-option to checked or unchecked a group of mat-list-options but i can't check that the mat-list-option is checked or not with $event.
You could also assign a template reference to the mat-list-option and check if it is selected
TemplateRef: #option then use option.selected
<mat-selection-list #shoes>
<mat-list-option #option *ngFor="let shoe of typesOfShoes">
{{shoe}} <div style="font-weight:bold">{{option.selected}}</div>
</mat-list-option>
</mat-selection-list>
Stackblitz
https://stackblitz.com/edit/angular-gl4wqq?embed=1&file=app/list-selection-example.html
<mat-list-option (click)="selectGroup($event.toElement.getAttribute('ng-reflect-state'))">
</mat-list-option>
ng-reflect-state keep an string value that show mat-list-option status, the value may be "checked" or "unchecked".

How to get descendants with a specific tag name and text in protractor?

I have the following structure (it's just for sample). In protractor, I am getting the top element by id. However, the other elements do not have id's. I need to get the "label" element that contains the text '20'. Is there an easy way in protractor to select the element with a specific tag that contains a specific text from all the descendants of a parent element?
<pc-selector _... id="Number1">
<div ...></div>
<div ...>
<div ...>
<check-box _...>
<div _ngcontent-c25="" ...>
<label _ngcontent-c25="">
<input _ngcontent-c25="" type="checkbox">
<span _ngcontent-c25="" class="m-checkbox__marker"></span>
20 More text to follow</label>
</div>
</check-box>
</div>
</div>
</pc-selector>
I could't find anythitng, so I have tried with xpath, but protractor complains that my xpath is invalid:
parentElement = element(by.id('Number1'));
return parentElement.element(by.xpath(".//label[contains(text(),'20'))]"));
Any ideas?
You have an additional bracket in your [contains(text(),'20'))] which is likely causing you issue but there are multiple other ways this can be achieved using a single XPath or chaining other locators.
The process is that you must find the div with the correct id first and then locate the label that is a child of it.
//Xpath
element(by.xpath("//pc-selector[#id='Number1']//label[contains(text(),'20')]"));
//Chained CSS
element(by.id('Number1')).element(by.cssContainingText('label','20'));
You also may be interested to learn about xpath axes which can allow us to do very dynamic selection.
You can use the direct xpath to access the label.
element(by.xpath("//*[#id='Number1']//label"));

New kind of Select_list found and don't know how to write the code for that

I have written code for select list this way b.select_list(:id,'something').select 'something' but I don't how know how to write a code for given below select list, Can anyone help me to write the code to select from this select_list
<md-select tabindex="0" class="ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" role="listbox" aria-disabled="false" aria-expanded="false" aria-invalid="true" aria-multiselectable="false" aria-required="true" aria-owns="select_container_5" aria-label="Gender" ng-model="user.gender" name="gender" required=""><md-select-value class="_md-select-value _md-select-placeholder" id="select_value_label_0"><span>Gender</span><span class="_md-select-icon" aria-hidden="true"></span></md-select-value><div class="_md-select-menu-container" id="select_container_5" aria-hidden="true"><md-select-menu class="ng-scope"><md-content>
<md-option tabindex="0" class="md-ink-ripple" id="select_option_3" role="option" aria-selected="false" value="Male"><div class="_md-text">Male</div></md-option>
<md-option tabindex="0" class="md-ink-ripple" id="select_option_4" role="option" aria-selected="false" value="Female"><div class="_md-text">Female</div></md-option>
</md-content></md-select-menu></div></md-select>
Based on the element tag, md-select, it looks like this select list is created by Angular Material. It is not a select element, which means you cannot use the usual select_list method. Instead, you need to manually interact with it. This involves:
Clicking the select list to open the list of options
Clicking one of the options
The following code will select an option by value. You could use a different locator as needed:
# Open the dropdown
browser.element(tag_name: 'md-select', name: 'gender').click
# Select an option (by value)
browser.element(tag_name: 'md-option', value: 'Female').when_present.click
A couple of notes:
As md-select is not a standard element, you need to locate it using the generic element method.
Make sure to use when_present (or another wait method) to ensure the options are displayed before selecting.

How to check box in Capybara if there are no name, id or label text?

I am newbie here. Please advise. How to select checkbox in my case?
<ul class="phrases-list" style="">
<li>
<input type="checkbox" class="select-phrase">
<span class="prase-title"> Dog - Wikipedia, the free encyclopedia </span>
(en.wikipedia.org)
<div class="prase-desc hidden">The domestic dog (Canis lupus familiaris or Canis familiaris) is a domesticated...</div>
</li>
The following doesn't work for me:
When /I check box "([^\"]+)"$/ do |label|
page.check(label)
end
step: And I check box "Dog - Wikipedia, the free encyclopedia"
If you can change the html, wrap the input and span in a label element
<ul class="phrases-list" style="">
<li>
<label>
<input type="checkbox" class="select-phrase">
<span class="prase-title"> Dog - Wikipedia, the free encyclopedia </span>
</label>
(en.wikipedia.org)
<div class="prase-desc hidden">The domestic dog (Canis lupus familiaris or Canis familiaris) is a domesticated...</div>
</li>
which has the added benefit of clicks on the "Dog - Wikipedia ..." text triggering the checkbox too. With that change your step should work as written. If you can't modify the html then things get more difficult.
Something like
find('span', text: label).find(:xpath, './preceding-sibling::input').set(true)
should work, although I'm curious how you're using these checkboxes from JS with nothing tying them to any specific value
Let's assume that you are prevented from changing the HTML. In this case, it would probably be easiest to query for the element via XPath. For example:
# Here's the XPath query
q = "//span[contains(text(), 'Dog - Wikipedia')]/preceding-sibling::input"
# Use the query to find the checkbox. Then, check the checkbox.
page.find(:xpath, q).set(true)
Okay - it's not as bad as it looks! Let's analyze this XPath so we can understand what it's doing:
//span
This first part says "Search the entire HTML document and discover all "span" elements. Of course, there are probably a LOT of "span" elements in the HTML document, so we'll need to restrict this:
//span[contains(text(), 'Dog - Wikipedia')]
Now we're only searching for the "span" elements that contain the text "Dog - Wikipedia". Presumably, this text will uniquely identify the desired "span" element on the page (if not, then just search for more of the text).
At this point, we have the "span" element that is adjacent to the desired "input" element. So, we can query for the "input" element using the "preceding-sibling::" XPath Axis:
//span[contains(text(), 'Dog - Wikipedia')]/preceding-sibling::input

Resources