Using select2 Dropdown value is not binded to my article - Angular - javascript

I'm trying to bind selected value in dropdown to my article which has property of same type as dropdowns source is. But somehow when I console log my article there is no value in my property which should hold an selected dropdown value.
Here is my code:
In typescript I have :
article: Article;
mainGroups: Group[];
subGroups: Group[];
On init I'm filling mainGroups and subGroups with data, like this:
ngOnInit() {
this._groupService.getAll().subscribe(groups => this.mainGroups = groups);
this._groupService.getAllSubGroups().subscribe(subgroups => this.subGroups = subgroups);
}
Later in html I'm looping values from my mainGroups and subGroups like this:
<div class="form-group">
<label class="control-label dash-control-label col-xs-3">Main group:</label>
<div class="col-xs-9">
<select class="form-control dash-form-control select2" style="width: 100%;"
data-minimum-results-for-search="Infinity" name="articleGroups" required [(ngModel)]="article.mainGroup">
<option disabled [ngValue]="null">-/-</option>
<option [ngValue]="group" *ngFor="let group of mainGroups">{{group.title}}</option>
</select>
</div>
</div>
<!--Sub group-->
<div class="form-group">
<label class="control-label dash-control-label col-xs-3">Sub group:</label>
<div class="col-xs-9">
<select class="form-control dash-form-control select2" style="width: 100%;" name="subGroup" required [(ngModel)]="article.subGroup">
<option disabled [ngValue]="null">-/-</option>
<option [ngValue]="subgroup" *ngFor="let subgroup of subGroups">{{subgroup.title}}</option>
</select>
</div>
</div>
As you can see guys I also wrote : [(ngModel)]="article.mainGroup" on first dropdown, and I said also: [ngValue]="group" *ngFor="let group of mainGroups"
So basically this [ngValue]="group" should get value out of *ngFor and store it into article.mainGroup?
But when I do an console log I can not see article.mainGroup property at all, even if it's defined there in article.ts model.. so that means article.mainGroup property is empty ( because is not visible in console.log(article)?

I guess you need something like this:
<select class="form-control" [(ngModel)]="size" name="sizeValue" #sizeValue="ngModel">
<option *ngFor="let size of sizes" [value]="size">{{size}}</option>
</select>
Note the #sizeValue="ngModel"
See my original answer here:
https://stackoverflow.com/a/46866804/1546042

Related

How to select value in dropdown based on objects property value - select and angular

I have a product which has a category, and while editing product I would like to display current category in dropdown ofcourse. And if user wants to change category in dropdown it is ok, but on load I would like to show selected current product's value.
Here is my html
<div class="form-group">
<label class="control-label dash-control-label col-xs-3">Products category:</label>
<div class="col-xs-9">
<select id="mainGroupSelectEdit" class="form-control dash-form-control select2" style="width: 100%;"
data-minimum-results-for-search="Infinity" name="mainGroupSelectEdit" required (change)="filterSubById(article.groupId)" [(ngModel)]="article.groupId">
<option [value]="helperService.IsItEmptyGuid()" [selected]="isDefaultSelected()">-/-</option>
<option [value]="group.id" *ngFor="let group of mainGroups" [selected]="group.id==='a0e25215-a60e-4444-b6ac-4521b7de4b37'">{{group.title}}</option>
</select>
{{article.mainGroup.id}}
</div>
</div>
When I run my app and open this form, as you can see I put {{article.mainGroup.id}} <- it's binded article to check is there id of category, and when I open form it looks like this:
So obliviously {{article.mainGroup.id}} holds a value, but I can not force <select> to display that value as selected...
Any help would be awesome, thanks a lot !
EDIT:
It's doing nothing, just selecting -/- if product has no group because then article.mainGroup.id would be empty guid..
isDefaultSelected() {
return this._globalHelperService.isEmptyGuid(this.article.mainGroup.id);
}
EDIT 2: By following Pranay Rana example, here is what I did :
1.) Select article
2.) Open modal
3.) Image when modal is opened:
As you can see, value is there, but nothing is selected in a modal.
Here is original code, not only img:
<div class="form-group">
<label class="control-label dash-control-label col-xs-3">Group:</label>
<div class="col-xs-9">
<select touch-enter-directive [ref]="ref" [nextFocusElement]="articleSubGroup" id="mainGroupSelectEdit" class="form-control dash-form-control select2" style="width: 100%;"
data-minimum-results-for-search="Infinity" name="mainGroupSelectEdit" required (change)="filterSubById(article.groupId)" [(ngModel)]="article.mainGroup.id">
<option [ngValue]="null">-/-</option>
<option [ngValue]="group.id" *ngFor="let group of mainGroups">{{group.title}}</option>
</select>
{{article.mainGroup.id}}
</div>
</div>
Probably select2 is making an issue?
Thanks
do like this
<select id="mainGroupSelectEdit" class="form-control dash-form-control select2" style="width: 100%;"
data-minimum-results-for-search="Infinity" name="mainGroupSelectEdit" required (change)="filterSubById(article.groupId)" [(ngModel)]="article.groupId">
<option [ngValue]="null" >-/-</option>
<option [ngValue]="group.id" *ngFor="let group of mainGroups">{{group.title}}</option>
</select>
In angular [select] is not needed it will select option based on id value you pass as [(ngModel)] to select element,also no need of emptyguid if your value is null then default option will get selected

Angular 5 how to bind drop-down value based on another drop-down

I have a select drop-down that i populate from an api, i want to be able to populate a second select drop-down based on the user's first choice and subsequently populate a second drop-down based on the user's second choice.
Say i have my input fields so
form.component.html
<div class="form-group col-sm-6">
<label> Category</label>
<select class="form-control" [(ngModel)]="product.productCategory" [formControl]="productForm.controls['productCategory']" require>
<option *ngFor="let item of categorys" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-sm-6">
<label> Product Type</label>
<select class="form-control" [(ngModel)]="product.productType" [formControl]="productForm.controls['productType']" require>
<option *ngFor="let item of productTypes" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-md-6">
<label>Sub-Category</label>
<select class="form-control" [(ngModel)]="product.subCategory" [formControl]="productForm.controls['subCategory']" require>
<option *ngFor="let item of subs" [value]="item.slug">{{item.name}}</option>
</select>
</div>
As it is i am binding the whole list to each individual select drop-down but i want the subCategory to be only those under the selected category and same then productType based on the subCategory selected.
This is how i retrieve the category as it is the parent selection
form.component.ts
fetchCategorys() {
this.categorySrv.fetchCategories().then((response: any) => {
this.categorys = response;
console.log(this.categorys);
})
.catch(error => this.error = error)
}
I am using same method to get the subCategory and productType respectively. As you can see it brings all the items in each section from db but i want to be able to bind subCategory based on the choice of category and also bind productType based on the choice of subCategory.
Note that console.log(this.categorys) displays the category with their respective subCategory and productType but i can't figure out how to make the binding correspond.
Template
<div class="form-group col-sm-6">
<label> Category</label>
<select class="form-control" (change)="categoryChange($event)" [(ngModel)]="product.productCategory" [formControl]="productForm.controls['productCategory']" require>
<option *ngFor="let item of categorys" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-sm-6">
<label> Product Type</label>
<select class="form-control" (change)="productTypeChanged($event)" [(ngModel)]="product.productType" [formControl]="productForm.controls['productType']" require>
<option *ngFor="let item of productTypes" [value]="item.slug">{{item.name}}</option>
</select>
</div>
<div class="form-group col-md-6">
<label>Sub-Category</label>
<select class="form-control" [(ngModel)]="product.subCategory" [formControl]="productForm.controls['subCategory']" require>
<option *ngFor="let item of subs" [value]="item.slug">{{item.name}}</option>
</select>
</div>
Component
public allProductTypes: ProductType[];
public allSubs: Category[];
public categoryChange( $event: Category ) {
this.productTypes = this.allProductTypes.filter( _productType => _productType.belongsTo( $event));
}
public productTypeChanged( $event: ProductType ) {
this.subs = this.allSubs.filter( _sub => _sub.belongsTo( $event ) );
}
So you bind your to the dropdown change events. Then, each time a category or product type is chosen, we filter the data that the dropdowns have available to show.
You will also probably have to reset the downstream choices, aka. when changing category, then reset product type and sub cat, because the new top level category might not allow for the old type and subcat values to exist.

ngChange a bunch of dropdowns

So I need to entirely change a group of drop downs that appear based on the selection of one dropdown. I believe ngChange is the way to go about it, but I am not entirely sure how to change between two sets of divs (or if that is even the best way of doing it.
So I have this dropdown:
<div class="input-group" theme="bootstrap" style="">
<label>Product Type</label>
<select class="dropdown-menu scrollable-menu form-control" style="" ng-model="event.etype" ng-change="setOptions()" id="etype">
<option value="" selected disabled>Select a Product</option>
<option ng-click="type = 'x'">X</option>
<option ng-click="type = 'y'">Y</option>
<option ng-click="type = 'z'">Z</option>
<option ng-click="type = 'q'">Q</option>
<option ng-click="type = 'w'">W</option>
</select>
</div>
If the choice is X, I need one set of drop downs (contained in one row), and if it is anything else, I need an entirely different set (contained in another row).
Here are how the drop downs look:
<div class="col-lg-3">
<label>Numbers</label>
<ui-select-match placeholder="Select Numbers">{{$item.admin_user.name}}</ui-select-match>
<ui-select-choices repeat="a in ams"> {{a.admin_user.name}} </ui-select-choices>
</ui-select>
</div>
</div>
<div class="row col-lg-12" id="nonX">
<div class="col-lg-3">
<div class="input-group" theme="bootstrap">
<label>Super Heroes</label>
<select class="dropdown-menu scrollable-menu form-control" ng-model="superhero" id="script">
<option value="" selected disabled>Select Superhero</option>
<option ng-repeat="superhero in superheroes" ng-value={{superhero}} ng-click="selectHeroe(superhero)">{{superhero.name}}</option>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="row col-lg-12" id="noniPad">
<div class="col-lg-3">
<div class="input-group" theme="bootstrap">
<label>Screen</label>
<select class="dropdown-menu scrollable-menu form-control" ng-model="event.screen" id="screen">
<option value="" selected disabled>Select Screen</option>
<option ng-repeat="screen in screens" ng-value={{screen}} ng-click="selectScreen(screen)">{{screen.name}}</option>
</select>
</div>
</div>
<div class="col-lg-3">
<div class="input-group" theme="bootstrap">
<label>Misc Asset</label>
<select class="dropdown-menu scrollable-menu form-control" ng-model="event.miscasset" id="miscasset">
<option value="" selected disabled>Select Misc Asset</option>
<option ng-repeat="miscasset in miscassets" ng-value={{miscasset}} ng-click="slectMiscAsset(miscasset)">{{miscasset.name}}</option>
</select>
</div>
</div>
</div>
<div class="row m-b-sm m-t-sm"></div>
</div>
The separate drop downs both appear in different rows. So I would need one row to appear if they select iPad and one row to appear if they do not select an iPad.
I would love some help. Thank you!
Your best option would be to set the dropdowns of each one depending on the parent selection. There's no need to create a duplicate div to hold both sets of dropdows.
I removed all css classes and any other markup not relevant to the ng-change to make it clearer.
Your parent dropdown would look like this:
<div>
<label>Product Type</label>
<select ng-model="event.etype" ng-change="setOptions(event.etype)">
<option value="">Select a Product</option>
<option ng-repeat="etype in etypes" ng-value="etype" ng-bind="etype"></option>
</select>
</div>
Take special notice of how the setOptions handler is being passed the ng-model value. This means when an option is selected, it'll automatically set ng-model="event.etype" to the value of that option.
To support this behavior in your controller you need to provide the array of event types:
$scope.etypes = ['gif', 'photo', 'ipad', 'video', 'print'];
Then, on your setOptions method you'll get the selected option and filter your descendant dropdowns
var options1 = [{
etype: 'ipad',
value: '1'
}, {
etype: 'gif',
value: '2'
}];
$scope.setOptions = function (etype) {
$scope.scripts = options1.filter(function (item) {
return item.etype == etype;
});
};
What this means is that setOptions will set the descendant dropdowns based on the etype value passed in. In this example I'm limiting to $scope.scripts only but you can set as many as needeed. As you can see options1 is just an array which contains the etype property which I need to filter against.
Finally on your descendant dropdowns you would use the filtered options:
<select ng-model="event.script">
<option value="" selected disabled>Select Script</option>
<option ng-repeat="script in scripts" ng-value="script.value" ng-bind="script.value"></option>
</select>
Using ng-hide="event.etype == null || event.etype=='ipad'" and ng-show="event.etype == 'ipad'" on the row tags solved my issue!

AngularJS - A dropdown is not retaining the selected values

In my AngularJS web application,
Plunker : https://plnkr.co/edit/x9uIx5Inkxxt3fqttkkK?p=preview
One of my drop down (First) is not retaining the selected value.
The html code fragment is below.
I know it is something to do with the mapping ng-model="entityPropertyType.propertyId"
The entityPropertyType is a iterated value from the list.
HTML
<div class="form-group" ng-repeat="entityPropertyType in advancedSearch.entityPropertyTypes" >
<label class="control-label col-md-1">Business Card</label>
<div class="col-md-2">
<select class="form-control" ng-model="entityPropertyType.propertyId"
ng-change="businessCardSelected($index, entityPropertyType.propertyId)" >
<option value="">Please select</option>
<option ng-repeat="property in businessCards" value="{{property.propertyId}}">{{property.propertyLabel}}</option>
</select>
</div>
</div>
You should never use ngRepeat to render select options. Use ngOptions directive:
<select class="form-control"
ng-options="property.propertyId as property.propertyLabel for property in businessCards"
ng-model="entityPropertyType.propertyId"
ng-change="businessCardSelected($index, entityPropertyType.propertyId)">
<option value="">Please select</option>
</select>
Demo: https://plnkr.co/edit/v6KbJSkqu5XNz2LUfbrK?p=preview

How to get selected value from dropdown in a table when there is more then 1?

If I have a bunch of table rows and with select tags in them how would I get the selected value?
If the variable "selected_ingr_action" is the same for every row then when I select an item they all change instead of just the one.
I know I'm missing something.
{{#Ingredients}}
<tr>
<td class="ingr-bid-col"></td>
<td>
<div class="row">
<div class="col-xs-12">
<p class="ingr-name">{{Name}}</p>
</div>
</div>
<div class="row">
<div class="col-xs-6">
{{VendorName}}<br />
<b>pack:</b><span>{{Pack}}</span>
</div>
<div class="col-xs-6" style="padding-bottom:5px;">
<div class="caption">
<b>unit price</b><br />
<span>{{UnitPrice}}</span>
</div>
<div class="caption">
<b>case price</b><br />
<span>{{CasePrice}}</span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<select class="form-control" value="{{selected_ingr_action}}">
<option value="-1" selected disabled>Action</option>
<option value="0">Rename</option>
<option value="1">Edit Unit Price</option>
<option value="2">Archive</option>
</select>
</div>
</div>
</td>
</tr>
{{/}}
I think perhaps you might be asking a much simpler question about why the rows are sharing the value. If this is the case, the short answer is to use a restricted reference (notice the .):
<select class="form-control" value="{{.selected_ingr_action}}">
<option value="-1" selected disabled>Action</option>
<option value="0">Rename</option>
<option value="1">Edit Unit Price</option>
<option value="2">Archive</option>
</select>
This causes the selected_ingr_action to be bound to the list item, not the root of the ractive instance.
You can access the result on each item with a wilcard observer:
r.observe('list.*.selected_ingr_action', function(n, o, k, i){
console.log('list index', i, 'changed from', o, 'to', n);
});
Check it out here.
The behavior of defaulting to root, rather than current context, is under consideration to be changed to resolve to the current context.
One option would be to have a separate map of selected values, and use two-way binding to update that map (rather than a single selected_ingr_action property, or a selected_ingr_action property belonging to each item in the list). You can see an example of this approach here - the details are different but the principle is the same.
{{#Ingredients :i}} <!-- note the index reference -->
...
<select class="form-control" value="{{selected_ingr_actions[i]}}">
<option value="-1" selected disabled>Action</option>
<option value="0">Rename</option>
<option value="1">Edit Unit Price</option>
<option value="2">Archive</option>
</select>
There are to ways to solve this.
First, bind the value of the select into data.
I.e. turn this string:
<select class="form-control" value="selected_ingr_action">
into this:
<select class="form-control" value="{{selected_ingr_action}}">
Assuming that your data structure is something like this:
var Ingredients = [
{
Name: String,
VendorName: String,
UnitPrice: Number,
CasePrice: Number,
selected_ingr_action: String
},
/* other entries */
];
As a second thought, maybe you don't want to store action type inside your data.
I beleive that better approach would be to use so-called Proxy Events with custom arguments and Method Calls.
Here, I add key into your template and when you change your select value, corresponding event handler are called with the index of your row.
Like this:
{{#each Ingredients: key}} <!-- <<< note that key -->
<!-- skip -->
<div class="row">
<div class="col-xs-12">
<select class="form-control" on-change="changeAction(this, key)" value="{{this.selected_ingr_action}}">
<!-- note this too ^^^^^^^^^^^^^^^^^^^^^^ -->
<option value="-1" selected disabled>Action</option>
<option value="0">Rename</option>
<option value="1">Edit Unit Price</option>
<option value="2">Archive</option>
</select>
</div>
</div>
{{/each}}
Note, into your Ractive component you can introduce method changeAction, which will receive current row (with corresponding Name, VendorName etc. properties) and it's key. Like this:
var ractive = new Ractive({
/* skip */
changeAction: function (ingridient, key) {
// do something with that ingridient
}
/* skip */
});

Categories

Resources