Here is a link to my project: https://stackblitz.com/edit/angular-ivy-scycva?file=src/app/form/form.component.ts
I initially have a dropdown, where the user selects one of three users: Jack, Nav, or Pom
After selecting user x, the details of x are displayed below.
I have three datas at the start, and initialize a current object:
datas: Data[] = [
new Data(1, "Jack", "jack#gmail.com", "123 Main"),
new Data(1, "Nav", "nav#gmail.com", "324 Murray"),
new Data(1, "Pom", "pom#gmail.com", "995 Fortran")
];
current: Data = this.datas[0];
The select dropdown selects current.name as the default value. The options are a list of objects inside datas, and we show the data.name property:
<select
id="person"
class="form-control"
[ngModel]="current.name"
#selectRef
(change)="updateSelect(selectRef.value)">
<option *ngFor="let data of datas" id="{{data.name}}" [value]="data.name">{{ data.name }}</option>
</select>
Below are a set of inputs in a form, which should contain data on the person selected:
<form #userForm="ngForm">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" name="name" [ngModel]="current.name">
</div>
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" name="email" [ngModel]="current.email">
</div>
</form>
Currently when an update occurs, I change the current object as follows:
updateSelect(event) {
this.current = this.datas.filter(d => d.name == event)[0];
}
I don't like this way because first of all, names can be the same, and secondly, I feel there must be a better way.
If possible, I want to be able to pass in the data object from the option selected so I can just do this.current = data, but I don't know if this is possible. I also don't want to expose anything like an id onto the option field, which the user should not be able to see.
Modified here https://stackblitz.com/edit/angular-ivy-v1pjhn?file=src%2Fapp%2Fform%2Fform.component.html
Previous
<select
id="person"
class="form-control"
[ngModel]="current.name"
#selectRef
(change)="updateSelect(selectRef.value)"
>
<option *ngFor="let data of datas" id="{{data.name}}" [value]="data.name">{{ data.name }}</option>
</select>
Now
<select
id="person"
class="form-control"
[(ngModel)]="current"
>
<option *ngFor="let data of datas" [ngValue]="data">{{ data.name }}</option>
</select>
Related
I want to select the first option in a select box by default. The challenge here is that the page might have multiple select boxes as they are created dynamically.
You will understand what I am trying to achieve by looking at my code.
HTML :
<form class="form-inline">
<div class="form-group form-group-grid" ng-repeat="fields in selectedTabData.requiredField" ng-switch="fields.paramType">
<label>{{fields.paramName}}<span class="asterisk" ng-if="fields.mandatory==true">*</span></label>
<input type="text" class="form-control" ng-switch-when="Text" ng-model="fields.fieldValue" ng-attr-id="{{fields.paramName}}Id">
<select class="form-control" ng-switch-when="DropDown" ng-options="field.paramKey as field.paramValue for field in fields.paramData" ng-model="fields.fieldValue" ng-attr-id="{{fields.paramName}}Id">
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary form-inline-grid-button" ng-click="getReport()">Run Report</button>
</div>
</form>
The selected data is available under the model $scope.selectedTabData.requiredField
In Controller I push the selected values in to a variable like :
$scope.selectedTabData.requiredField.forEach(function(item)
{
paramValue.push(item.fieldValue);
paramName.push(item.paramName);
})
I tried doing this :ng-init="fields.fieldValue = fields.paramData[0]"
<select class="form-control" ng-switch-when="DropDown" ng-options="field.paramKey as field.paramValue for field in fields.paramData" ng-model="fields.fieldValue" ng-init="fields.fieldValue = fields.paramData[0]" ng-attr-id="{{fields.paramName}}Id">
</select>
I am not sure how it will work. Can anyone help me out with this?
you can make it possible by ng-repeat inside tag
<select ng-model="fields.fieldValue">
<option ng-repeat="field in fields.paramData" value="{{field.paramKey}}">
{{field.value}}
<option>
</select>
and in controller add this line
$scope.fields.fieldValue = x;
and in this example, x is "field.value" that you want as default selected option.
This is the plunkr for your problem
https://plnkr.co/edit/mahONdv5xQBa5eUZJSoX
I use Angular2, and have html code
<div class="row">
<div class="col-xs-3 form-group">
<select class="form-control"
id="country"
[(ngModel)]="testSelectModel"
(change)="testSelectChange($event)">
<option *ngFor="let item of textCollection"
[value]="item.id">
{{item.name}}
</option>
</select>
</div>
<div class="col-xs-3 form-group">
<input type="text"
class="form-control"
[(ngModel)]="testSelectModel"/>
</div>
</div>
I also have a collection of textCollection, objects which - {
name: 'foo',
id: 1
}...
I enter (id) in input 1, and wanted see selected item in tag select.
Yes, all is well, the item has changed, but the event "testSelectChange" - is not invoked..
example
Somebody faced such?
If you modify the input, testSelectChange() won't get called, even though the select DOM element and the input DOM element are both bound to the same component property, testSelectModel. Angular will only call testSelectChanges() if there is a change to one of select's DOM properties, and this doesn't happen when you change the input value.
I suggest breaking up the event and data binding – use [ngModel] and (ngModelChange) – for each binding:
<select [ngModel]="testSelectModel"
(ngModelChange)="testSelectChange($event)">
...
<input [ngModel]="testSelectModel"
(ngModelChange)="testInputChange($event)">
Note that $event will be set to the current value of the select or input.
Then manually call the the select change event handler from testInputChange():
testSelectChange(newValue) {
console.log('testSelectChange', newValue);
this.testSelectModel = newValue;
this.resultWorkModel = newValue;
}
testInputChange(newValue) {
console.log('testInputChange', newValue)
this.testSelectModel = newValue;
this.testSelectChange(newValue); // manually trigger other event handler
}
Plunker
Besides what the other commenters have said, you might also need to write your handler in a Future, because the changes to testSelectModel might not have taken effect before testSelectChange($event) has happened.
This was the case in Angular1.
This should work:
Plunker Code
html:
<select class="form-control" #type [(ngModel)]="testSelectModel" (change)='testSelectChange(type.value)'>
<option *ngFor="#item of textCollection" [value]="item.id">
{{item.name}}
</option>
</select>
class:
testSelectChange(val: string) {
console.log('I call', val);
this.resultWorkModel = this.textCollection.find((obj) => obj.id == val).name;
}
The event for handle changes in the model is ngModelChange, your code should be like this:
<div class="row">
<div class="col-xs-3 form-group">
<select class="form-control"
id="country"
[(ngModel)]="testSelectModel"
(ngModelChange)="testSelectChange($event)">
<option *ngFor="let item of textCollection"
[value]="item.id">
{{item.name}}
</option>
</select>
</div>
<div class="col-xs-3 form-group">
<input type="text"
class="form-control"
[(ngModel)]="testSelectModel"/>
</div>
</div>
This is a example in Plunker Enjoy.
I have the following select:
<select selected="windows" ng-model="wdtype[4][$index]" id="inputEmail1" class="form-control">
<option>app1</option>
<option>app2</option>
<option>app3</option>
</select>
I want that every time that the user select option, the field inputName3 will be reflected. The field defines like this:
<input type="text" class="form-control" ng-model="wdname[4][$index]" id="inputName3" placeholder="Machine Name" disabled>
For example, the user select app1, so the name will be m-app1. If the user select app2, the name will be displayed: m-app2.
I don't see any trigger in angular which can help me in this case.
You can define values for options like this
<option value="m-app1">app1</option>
<option value="m-app2">app2</option>
<option value="m-app3">app3</option>
Or make it in a generic way. Define a function in scope that transforms selected value the way you need.
In controller:
$scope.getMachineName = function () {
if (wdtype[4][$index]) return '';
return 'm-' + $scope.wdtype[4][$index];
}
In template
<input type="text" class="form-control" value="{{getMachineName()}}"
I'm using Angular for a SPA I'm working on. I have an array which contains objects for each user on my site. I have an ng-repeat to add all the users to my dropdown list. I'm trying to figure out how do I display specific user information in an input box based on the selected user from the drop down?
<select id="entityDropDown" ng-options="user.name for user in users" ng-change="userInfo(user)"></select>
<div>
<label for="entityId">ID: </label>
<input type="text" id="entityId" disabled ng-model="{{user.id}}"/>
</br>
<label for="entityDomain">Domain: </label>
<input type="text" id="entityDomain" disabled ng-model="{{user.domain}}"/>
</div>
app.controller('userCtrl',
function userCtrl($scope,siteCollection){
$scope.users = siteCollection.getUsers();
}
);
K I solved the issue.
First of all, this ng-model="{{user.domain}}" isn't how you use ng-model. I had to change them to remove the curly braces ng-model="user.domain".
I modified the select as such:
<select id="entityDropDown"
ng-model="selectedUser"
ng-options="user as user.name for user in users"
ng-change="userInfo(selectedUser)">
</select>
This is my controller function:
spApp.controller('userCtrl',
function userCtrl($scope,siteCollection){
$scope.users = siteCollection.getUsers();
$scope.selectedUser = {};
$scope.userInfo = function(user) {
$scope.selectedUser = user;
};
}
);
Basically the controller gets all my users and puts it in a user object. The select goes through each user and generates the options. When the selected option changes, the ng-change passes the selected user object to the userInfo function and the html populates with that objects information.
you can append ng-model="selectedUser" to your select and in your userCtrl
<!-- template.html -->
<select id="entityDropDown" ng-options="user as user.name for user in users" ng-model="selectedUser">
</select>
<div class="user-info" ng-show="selectedUser">
<p> {{selectedUser.name}}</p>
<!-- ... -->
</div>
in your controller
// controller.js
function userCtrl($scope, siteCollection){
$scope.users = siteCollection.getUsers();
$scope.$watch('selectedUser', function(oldVal, newVal) {
if (oldVal === newVal) return;
//do something like call JSON if need it
});
}
When the <select> changes the $scope.selectedUser changes to selected value. later you can use the selectedUser variable like holder for your show the info into other place like in the div.user-info or you can use $scope.$watch('selectedUser'... for fire other behavior like call a services or whatever
using your template
<select id="entityDropDown" ng-options="user in users" ng-model="selectedUser">
<!-- <option ng-repeat="user in users">{{user.name}}</option> -->
</select>
<div>
<label for="entityId">ID: </label>
<input type="text" id="entityId" disabled ng-model="selectedUser.id"/>
</br>
<label for="entityDomain">Domain: </label>
<input type="text" id="entityDomain" disabled ng-model="selectedUser.domain"/>
</div>
I am new to Angular so I think this is a basic concept that I'm just missing some step on. I want to have a search that does basic angular filtering, but I want to have a separate select that chooses what the text input searches on. Currently it looks like this:
Search inputs:
<input type="text" class="form-control" id="search-users" ng-model="userQuery">
<span class="input-group-btn">
<select ng-model="searchOn" ng-change="setSearchOn(searchOn)">
<option value="CustomerId" selected>CustomerId</option>
<option value="Username">Username</option>
</select>
</span>
Function:
$scope.setSearchOn = function(searchOnIn){
console.log("setting searchOn to "+searchOnIn);
$scope.searchOn = searchOnIn;
}
Repeater:
<div ng-repeat="user in users | filter:userQuery.searchOn">
I feel like i shouldn't even need the function, shouldn't i be able to data-bind the value of the select to the filter on the repeater? I couldn't get that to work either. Help would be appreciated. Angular is awesome, but the beginning learning the way it works is a little rough :)
As I understand it, we want to pick the property which we search on with the dropdown, and then search that property for value on the userQuery input.
One way to accomplish that is to (re)build an object to filter with when either userQuery or searchOn alters.
var app = angular.module('myapp', []).controller('ctrl', function($scope){
/* some test data */
$scope.users = [{CustomerId : 1, Username : 'Pete'},
{CustomerId : 2, Username : 'John'},
{CustomerId : 3, Username : 'Claus'}]
$scope.setSearchFilter = function()
{
$scope.searchFilter = {};
$scope.searchFilter[$scope.searchOn] = $scope.userQuery;
}
})
In the html, I've set an ng-change on both the userQuery and searchOn to update the search filter.
<div ng-controller="ctrl">
<input type="text" class="form-control" id="search-users" ng-model="userQuery" ng-change="setSearchFilter()" />
<span class="input-group-btn">
<select ng-model="searchOn" ng-change="setSearchFilter()">
<option value="CustomerId" selected>CustomerId</option>
<option value="Username">Username</option>
</select>
</span>
<div ng-repeat="user in users | filter:searchFilter">
{{user.CustomerId}} -- {{user.Username}}
</div>
</div>
http://jsfiddle.net/nwdx7/1/