Using <p-dropdown> with form control - html

I think I am having an issue with value binding. I have 2 dropdowns on my page currently. The rest of the page is using PrimeNg for UI and would like to make these dropdowns look the same as the rest of the page. How should I go about making this work.
One dropdown is a supervisor list.
<div class="ui-g form-group">
<label for="supervisors">Supervisors * </label>
<select
class="form-control"
id="supervisors"
required
[(ngModel)]="model.supervisor"
name="supervisor"
>
<option *ngFor="let sup of supervisors" [value]="sup">
{{sup}}
</option>
<div
[hidden]="supervisors.valid || supervisors.pristine"
class="alert alert-danger"
>
Supervisor is required
</div>
</select>
</div>
The other is a leave code list
<div class="ui-g-12 ui-md-1" id="test">
<label for="codes">Leave Codes * </label>
<select
class="form-control"
id="codes"
placeholder="Select Leave Code *"
required
[(ngModel)]="model.code"
name="code"
>
<option *ngFor="let cod of codes" [value]="cod">{{cod}}</option>
</select>
</div>
I have 2 arrays of values being called from my .ts file
supervisors = ['Alex',"Jones",'Joe','Rogan'];
codes = ['Personal Leave','Vacation Leave', 'Sick Leave'];
When I use the tags I just get an empty drop down. I tried just using initially but then I was not able to get the required fields to validate.

Did you import DropdownModule?
import {DropdownModule} from 'primeng/dropdown';
See the documentation, html binding should be
<p-dropdown [options]="supervisorList" [(ngModel)]="supervisor"></p-dropdown>
where supervisorList will be defined as SelectItem in controller and needs to be in a label + value format.
supervisorList: SelectItem[];
this.supervisorList= [
{label: 'Alex', value: 'Alex'},
...
];

Related

How to get validate select depending on another select

I have a doctor list. And each doctor has his procedures. How can I apply selected doctor's procedures to procedures selection.
html
<div class="form-group">
<label for="doctors">Doctor</label>
<select [formControl]="selectControl" class="form-control" id="doctors">
<option value="doctor"*ngFor="let doctor of doctors">{{doctor.username}}</option>
</select>
</div>
<div class="form-group">
<label for="procedures">Select Procedure</label>
<select *ngIf="selectControl.valid" class="form-control" id="procedures">
<option *ngFor="let p of selectControl.value.procedures">{{p}</option>
</select>
</div>
.ts
selectControl: FormControl = new FormControl();
For select control, the option value has to be binded to [ngValue] instead of value property.
Here is a working sample showing how to bind to doctors array and then how to retrieve the value of the selectedProcedure.
PS - Instead of creating a formControl, I personally find it more convenient to use formBuilder instead

Is it possible to display certain number of objects from a list in a dropdown? (but keep rest available for search)

In my dropdown for now all of the products are displayed, and I have like 200 products there, and dropdown is pretty large, I would like to display only 5-10 product for example, so it might look like this:
So basically all of the products would be there available for search, BUT ONLY 5 - 10 of them would be displayed, so dropdown would look more cleaner..
This is pure html of dropdown:
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<option>258-656 - Product 1 0,5l</option>
<option>358-656 - Product 2 0,75l</option>
<option>428-656 - Product 3 1kg</option>
</select>
</div>
And this is Angular modified:
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<option *ngFor="let p of products;" [value]="p.id">{{product.title}}</option>
</select>
</div>
And this angular way of course display all the values that are contained in products array.. and that's not it:)
Any kind of help would be awesome
Thanks guys
Cheers
In your component, import FormControl from #angular/forms and create an observable that takes a Product[].
public productCtrl: FormControl = new FormControl();
public products$: Observable<Product[]>;
now introduce a cold-observable that listens to input on the form-control, but until then, display the first 5 items.
this.products$ = this.productCtrl.valueChanges.pipe(
debounceTime(500),
startWith(null)
map(this.filterOrFirstFiveElements)
// implement a function
// that filters and returns your current product array or returns first five elements
// when a filter is provided and you get more that five elements, you can still only return first five elements of that result
);
Now in your template go ahead and adjust it to use the observable and mark the control as form-control.
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<option *ngFor="let p of products$ | async;" [value]="p.id">{{product.title}}</option>
</select>
</div>
<input type="text" [formControl]="productsCtrl" />
You need to import reactive-forms module into your module in order to be able to use [FormControl] directive.
Not directly related: As a user I would be completely confused when I see only five elements, use the filter and get a completely different result. An autocomplete is maybe a better solution. Show nothing, until user searches for a product.
Use Pipe
filter.pipe.ts
transform(value: any, args?: any): any {
console.log(args)
if(!value){
return null;
}
let arg=args ? args :5;
let limitTo=value.length >5 ? value.slice(0,arg) : value ;
return limitTo;
}
HTML
<div *ngFor="let d of data |filterpipe:5">
{{d.name}}
</div>
Example:https://stackblitz.com/edit/angular-r3kpxc
You could just use an index:
<div class="col-sm-6">
<select class="form-control dash-form-control select2" style="width: 100%;">
<option selected disabled>Search...</option>
<ng-container *ngFor="let p of products; let i = index;" >
<option *ngIf="i < 5" [value]="p.id">{{product.title}}</option>
</ng-container>
</select>
</div>

How to format multiselect form data in JSON

I have a template driven form which has multiselect field called assets.
I am using semantic UI.
<div ngModelGroup="assets">
<div class="field">
<label for="resourceName">Assets</label>
<div class="form-control">
<select ngModel name="resourceName" multiple="" #resourceName="ngModel" id="multi-select" class="ui dropdown" required>
<option *ngFor = "let x of resources" value ="{{x.resourceName}}" >{{ x.resourceName }}</option>
</select>
</div>
</div>
</div>
the json I am getting from the dropdown is in the format:
"assets":{"resourceName":["laptop","keyboard"]}
but I want it in this format:
"assets":[{"resourceName":"laptop"},{"resourceName":"keyboard"}]
How do I do that?
You could use map transformation over array to get desired output.
this.resources = this.assets.resourceName.map(i => { resourceName: i})

Angular2 and Html forms - issue with two way databinding blank, required, selected

I am generating an array based on a number that is input by the user:
<div class="form-group">
<input type="number"
class="form-control"
id="numPeople"
[(ngModel)]="numPeople"
name="numPeople"
required>
</div>
With this number, I generate an array of [['name', 'gender'],*number...]. I am then trying to use ngForm to bind directly into this array and I wanted to have a gender set as default but having trouble with it in two ways:
1) is not working so I can't have a default value in the select, and required is not forcing an entry so you can press submit without selecting an option even with the required flag set.
2) I am getting this error when I delete the placeholder text being read in from 2 way databinding into the input box, and if I try insert a blank string, i.e. by putting '' into the array on the backend: [ '', '' ]
EXCEPTION: Error in ./SellTicketComponent class SellTicketComponent -
inline template:373:28 caused by: If ngModel is used within a form
tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.
Example 1: <input [(ngModel)]="person.firstName" name="first">
Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}"> ErrorHandler.handleError #
error_handler.js:54 next # application_ref.js:359 schedulerFn #
async.js:93 SafeSubscriber.__tryOrUnsub # Subscriber.js:223
SafeSubscriber.next # Subscriber.js:172 Subscriber._next #
Subscriber.js:125 Subscriber.next # Subscriber.js:89 Subject.next #
Subject.js:55 EventEmitter.emit # async.js:79 NgZone.triggerError #
ng_zone.js:331 onHandleError # ng_zone.js:292 ZoneDelegate.handleError
# zone.js:246 Zone.runTask # zone.js:154 ZoneTask.invoke # zone.js:345
error_handler.js:56 ORIGINAL EXCEPTION: If ngModel is used within a
form tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.
Example 1: <input [(ngModel)]="person.firstName" name="first">
Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">
This is the code:
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
<label> Enter the details of all your plus ones for the guest list: </label>
<br>
<div *ngFor="let guest of guests; let i = index;">
<label> Enter First and Last Name:</label>
<div class="form-group">
<input type="text"
class="form-control"
id="{{guest[0]}}"
[(ngModel)]="guest[0]"
name="{{guest[0]}}"
required>
</div>
<div class="form-group">
<label> Enter Gender: </label>
<select
class="form-control"
id="{{i}}"
name="{{i}}"
[(ngModel)]="guest[1]"
required>
<option value="female" selected>
female
</option>
<option value="male">
male
</option>
</select>
</div>
</div>
</form>
Not really knowing how you generate your guests and how they look like.... since you seem to use [(ngModel)]="guests[0]", I would assume you'd want to use [(ngModel)]="guests[i]" instead. Here is an example using the latter.
If you want to use two way binding for the guest, when you generate the guests, you can preset the gender value to female, so that it will be preselected in the dropdown, e.g:
this.guests.push({name:'',gender:'female'}, {name:'',gender:'female'});
If you don't need the two way binding for guests, you can use e.g [(ngModel)]="selected", where in your component you have declared selected: string = 'female'. That will work as well.
So all in all your form could look like this:ยจ
<button (click)="generate()">Generate 2 Guests</button> <!-- dummy button -->
<form (ngSubmit)="onSubmit(f.value)" #f="ngForm">
<label> Enter the details of all your plus ones for the guest list: </label>
<div *ngFor="let guest of guests; let i = index;">
<label> Enter First and Last Name:</label>
<div>
<input type="text" name="guest{{i}}" [(ngModel)]="guests[i].name" required>
</div>
<div>
<label> Enter Gender: </label>
<select name="gender{{i}}" [(ngModel)]="guests[i].gender" required>
<option value="female">female</option>
<option value="male">male</option>
</select>
</div>
</div>
<button type="submit">Submit</button>
</form>
This will check the validity of the fields. Here of course user can enter just white spaces, so you'd need to check that as well.
Here's a Demo Plunker (which does not check white spaces)
Hope this helps! :)

enable checkbox with id only

I want to fill a HTML form, I am using mechanize module of python.
my HTML code is like that for checkbox and dropdown is :
<div id="post_cd">
<input role="checkbox" id="cd_info" class="cbox" type="checkbox">
<span class="s-iso" style="display:none"></div>
<label for="type" id="cdtype" class="cd" style="width:60px;margin:1px;float:left;text-align:right;">CD type:</label>
<select id='cdtype' class=" ui-iso" style="width:100px;margin:1px;float:left;">
<option value="CD1">Error1</option>
<option value="CD2">Error1</option>
<option value="CD3">Error2</option>
</select>
I have tried with following but getting errors:
for checkbox: form.find_control("cd_info").items[0].selected = True
for dropdown: form['cdtype']= ['Error1']
error:
raise ControlNotFoundError("no control matching "+description)
mechanize._form.ControlNotFoundError: no control matching name 'cd_info'
raise ControlNotFoundError("no control matching "+description)
mechanize._form.ControlNotFoundError: no control matching name 'cdtype'
There is no <form> in your HTML code. So probably form is not pointing to an element around the HTML code you provide at the moment you call find_control or the subscription operator.
You can try to print the text of the form to be sure you are looking at the right thing:
print form