How to access selected option in Angular.js controller - javascript

I have two selects, the contents of second must depends on selected value at first select. E.g. I want to load list of companies (to 2nd <select>) which providing particular service (selected in 1st <select>):
<div ng-controller="GetCompaniesByService as class">
<select ng-options="service.name for service in class.services" ng-model="selectedService"></select>
Chosen service_id: {{ selectedService.id }}
<select ng-options="company.name for company in class.companies" ng-model="selectedCompany"></select>
</div>
How to access in controller current selectedService.id value from model?
Е.g I need to dynamically load data via ajax, from url like this
$http.get('http://127.0.0.1:3000/service/'+selectedService.id)
to use it in second <select>

you have to watch for selectedService in your controller scope. First initialize the value of selectedService to "false", then when the user will change the option selectedService will get the value of the select.
Once the value of selectedService became different from "false" show the second select/option.
your html :
<div ng-controller="GetCompaniesByService as class">
<select ng-options="service as service.name in class.services" ng-model="selectedService"></select>
Chosen service_id: {{ selectedService.id }}
<select ng-options="company as company.name in class.companies" ng-model="selectedCompany" ng-show="selectedService"></select>
</div>
your controller :
app.controller('GetCompaniesByService',function($scope){
$scope.class = {}; //initialize the class object
$scope.class.services = [...]; //your first $http request
$scope.selectedService = false;
$scope.class.companies = function(){
if(selectedService){
return $http.get('http://127.0.0.1:3000/service/'+selectedService.id)
.success(function(data){return data;})
.error(function(error){return [];});
}
else{
return [];
}
};
});

Related

Select first element in dropdown in Angular 7

I am getting content of dropdown list as a Map<number, string>. When I get the map, it is received sorted according to keys in ascending order.
While showing it in html, I am setting pipe keyvalue and provided a function to sort the items in ascending order of values.
Now, I am trying to select first element of this dropdown, but unable to do so.
I have tried jQuery method to select the first element.
I have tried to set ngModel of the select box to first value of the map, but it sets the value to the first value received in the Map which is sorted by key.
My HTML:
<select class="form-control" id="empId" [(ngModel)]="empId" [disabled]="!isEditable">
<option *ngFor="let emp of empNames | keyvalue:descOrder" [value]="emp.key">{{ emp.value }}</option>
</select>
My ts file:
this.commonService.getEmployeeList())
.subscribe((response) => {
this.empNames = response;
this.empId = this.empNames.keys().next().value;
});
data I am sending from server is:
{id:1,name: "Tim"},
{id:6,name: "Martha"},
{id:5,name: "Alex"},
{id:8,name: "Stacy"}
data I am receiving on screen is like:
Alex
Martha
Stacy
Tim
with Tim pre-selected
what I need is Alex should be pre-selected.
Then set the empId before subscribing.
this.empId = 5;
this.commonService.getEmployeeList())
.subscribe((response) => {
this.empNames = response;
});
Of course you might want another logic based on some kind of order. You can never be sure how the data are going to be received.
In this case you need to send the order from your api and filter by order.
Working Demo
<option *ngFor="let emp of empNames | keyvalue:descOrder" [value]="emp.key" [selected]="emp.id === 1">{{ emp.value }}</option>
you can use selected attribute like above
I would highly recommand you to use Angular's reactive forms! And set the select's value to the one you want, when you recieve your data. Don't use ngModel as it is deprecated and should have been removed by Angular 7 (Or will be soon). Check this
The best way to pre select an option is to use ngModel as you tried. Your list is sorted by keys so what you want is not to select the first item, yes it's the first but in other order so or you change the order in code or you search for the item you want to select and stores it to set on model.
I would suggest some changes that should improve the code and fix your problem.
<select class="form-control" id="empId" [(ngModel)]="currentEmployer" [disabled]="!isEditable">
<option *ngFor="let emp of employers$ | async" [value]="emp">{{ emp.value }}</option>
</select>
And order your list in a pipe with the function you prefer.
public currentEmployer: Employer = null;
private sortByNameAscending(e1, e2) {
return e1.name > e2.name ? 1 : 0;
}
this.employers$ = this.commonService.getEmployeeList().pipe(
switchMap(employers => {
const sortedList = employers.sort(this.sortByNameAscending);
if (sortedList.length > 0) {
this.currentEmployer = sortedList[0];
}
return sortedList;
})
);

Dependent dropdown menu in different collection

I'm new in Meteor. I'm trying to make dropdown menu dependent in other dropdown. The first one for client name in Customers collection & the second for the client address in Addresses collection. I've 2 collections Customers & Addresses. This is my code but don't know what to do next.
EDIT: i put both templates in another template called new order
HTML:
<template name="selectClient">
Client Name :
<select class="select">
<option selected disabled>Choose client name</option>
{{#each custom}}
<option>{{clientName}}</option>
{{/each}}
</select>
</template>
<template name="selectAddress">
Address:
<select class="select" name="Choose the address">
<option selected disabled>Choose the address</option>
{{#each address}}
<option>{{addressName}}</option>
{{/each}}
</select>
</template>
main.js
Template.selectClient.helpers({
'custom': function(){
return Customers.find();
}
});
Template.selectAddress.helpers({
'address': function(){
return Addresses.find();
}
});
var clientName= $('[name="newName"]').val();
var mobNumber = $('[name="newMob"]').val();
var age = $('[name="age"]').val();
var radioValue= $('[name="gender"]').val();
Customers.insert({
clientName: clientName,
age: age,
radioValue:gender,
createdAt: new Date()
});
var addressName = $('[name="addressName"]').val();
var detail = $('[name= details]').val();
Addresses.insert({
addressName: addressName,
detail: detail,
createdAt: new Date()
});
Customers = new Mongo.Collection('customers');
Addresses = new Mongo.Collection('addresses');
Mobile = new Mongo.Collection('mobile');
Since you are using two templates in parallel (and not in a parent-child relation) you may use a ReactiveVar to cache the current selected client name:
const selectedCustomer = new ReactiveVar()
Note, that it needs to be accessible for both templates. Either you declare it with both templates in one file or your use import / export to provide access over many files.
Now your customers select needs to have a value assigned to each option, so we can cache it on selection change:
<template name="selectClient">
Client Name :
<select class="select-customer">
<option selected disabled>Choose client name</option>
{{#each custom}}
<option value="clientName" selected="{{#if selectedClient clientName}}selected{{/if}}">{{clientName}}</option>
{{/each}}
</select>
</template>
I renamed it's class, to prevent confusion in naming, to select-customter. Noticed the {{#if selectedClient}}... code? We will use a helper to restore the last selected state on the dropdown. Otherwise your dropdown selection will reset on the next rendering cycle:
Template.selectClient.helpers({
'custom': function(){
return Customers.find();
},
selectedClient(name) {
const selected = selectedCustomer.get()
return selected && selected.clientName === name
}
});
We get the selected customer from the cache and check if the current option's value is the same. If true we can flag the option as selected.
Now you still need an event that covers the selected client:
Template.selectClient.events({
'change .select'(event, templateInstance) {
// get the value using jQuery
const value = templateInstance.$(event.currentTarget).val()
// update the ReactiveVar
selectedCustomer.set({ clientName: value })
}
})
It saves the selected value (currently the clientName) in a query-able format. Now in your adresses you just need to query all Adresses documents using the cached selected client:
Template.selectAddress.helpers({
'address': function(){
const query = selectedCustomer.get() || {}
return Addresses.find(query);
}
});
If a client is selected it will server as the query, otherwise all adresses will be returned.
The good thing is, that this ReactiveVar already provides you the capability to trigger a new rendering cycle if it updates, since your helpers' code relies on it and Blaze automatically resolves this for you.
Modificatopns
This code assumes, that Adresses have a relation to Customers by a field named clientName. If you have stored the relation by using other fields, such as _id - clientId you need to modify your code accordingly.
You could also hide the second dropdown and only display it, if there is a value in selectedCustomer.

AngularJS changing dropdown value with ng-model

nameList contains [“Julia”, “Evan”, “Tomas”];
select ng-model=“names” ng-options=“x for x in nameList”
In controller, I have a service api call GetNameByID/{id}”and depending on the id, I want to initialize the dropdown value of the modal form.
So if the user clicks ID 1, the dropdown defaults to Julia.
The problem is within the service call, when I try to initialize the model by doing $scope.names = data, it adds an empty option at the top instead of selecting Julia. When I console.log(data), it prints “Julia” but it becomes <option value=“?”></option>
How can i fix this?
So Lets have a HTML example for this case:
<div ng-app ng-controller="MyCtrl">
<select ng-model="names" ng-options="item for item in nameList">
</select>
<p>Selected : {{names}}</p>
<button ng-click="Update(2)"> Update(1)</button>
</div>
and Conrtoller has one service call which update your dropdown accordingly based on index.
function MyCtrl($scope) {
$scope.names = "Julia"
$scope.nameList = ["Julia", "Evan", "Tomas"];
$scope.Update = function(_value){
$scope.names = $scope.nameList[ parseInt(_value)] ;
}
}
Please have a look into running code, jsfiddle.
You can just use ng-init to initialize the dropdown first value like so:
<select ng-model="names" ng-init="names = data[0]" ng-options="x for x in data">
<option value="">Select</option>
</select>
Where [0] in data[0] is the position of the array.
Here is an example where you can set the option
In html file
<select ng-model="selectedName" ng-options="x for x in nameList"></select>
In js file
app.controller('myCtrl', function($scope) {
var id = 1;
$scope.names = ["Julia", "Evan", "Tomas"];
$scope.selectedName = $scope.names[id-1]; <---- here you can pass you id.
});
subtract id with 1 because array start with 0. Hope this is what you want to acheive.

Angular select, ng-init with dynamic value

I'm trying to get a select box working in Angular. The problem I'm experiencing is to do with ng-init and setting it's default value from an object which is created during runtime. Heres my code:
<select
ng-model="settings.editing.panel.data.production_company"
ng-change="settings.editing.panel.data.production_company = selectValue"
ng-init="selectValue = settings.editing.panel.data.production_company"
>
<option
ng-repeat="(key, value) in lists.production_companies"
value="{{key}}"
ng-selected="{{selectValue}}"
>
{{value}}
</option>
</select>
"lists.production_companies" is a simple key-value array of names, populated during initial page render, updated by ajax.
The object "settings.editing.panel.data" starts its life as NULL, but later is loaded with a correctly formatted object which contains the property "production_company".
I have found setting ng-init to something like "ng-init="selectValue = 3" works fine. Setting a $scope.test = 3, then setting "ng-init="selectValue = test" works fine too.
However, my dynamic value does not work. How can I use my dynamically created object to set the value of this select box during runtime with the set-up I have?
<select
ng-model="settings.editing.panel.data.production_company"
ng-options = "option as option.keyName for option in list.production_companies"
> <!--set keyName equal to your object's key-->
</select>
Then in your controller
$scope.settings.editing.panel.data.production_company = list.production_companies[0] // Or which value you want to assign
You question confused me somehow. The following snippet is a working one, is that what you want?
'use strict';
angular.module('DemoApp', []);
angular.module('DemoApp').controller('DemoCtrl', ['$scope', function($scope){
$scope.lists={
production_companies: { "0": "prod 1", "1":"prod_2" },
};
$scope.settings={
editing: {
panel: {
data: null
}
}
};
$scope.setData=function(data){
$scope.settings.editing.panel.data={
production_company: data
};
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="DemoApp" ng-controller="DemoCtrl">
<select ng-model = "settings.editing.panel.data.production_company">
<option ng-repeat = "(key, value) in lists.production_companies" value = "{{key}}">{{value}}</option>
</select>
<div>You select: {{settings.editing.panel.data.production_company}}</div>
<button ng-click="setData('0')">Set Data to Prod1</button>
<button ng-click="setData('1')">Set Data to Prod2</button>
</div>
In my circumstances I was able to change my backends data format to set an object like:
{"id": 1, "name":"prod comp 1"}
and then change my select model accordingly. In hindsight I needed this for the ID anyway.
<select
ng-model="settings.editing.panel.data.production_company"
>
<option
ng-repeat="option in settings.lists.production_companies"
value="{{option.id}}"
ng-selected="{{option.id}} == settings.editing.panel.data.production_company"
>
{{option.name}}
</option>
</select>

ng-select won't recognise the ng-model is a valid option and should be selected

I have an angular app that contains a form, which has a select. I can choose one of the selects, and its updated in the model perfectly. But the next time i go in the form its suppose to be "pre filled" as the data already exists. And all the data is filled ok, but angular doesn't seem to recognise that the value of the model corresponds to the value of the select.
html/angular:
<select ng-model="userData.country"
ng-options="country as country.name for country in countries">
</select>
data
[
{"iso":"DK","name":"Danmark"},
{"iso":"DE","name":"Germany"}
]
The wanted behaviour is that once I set this data to userData.country, that the form will come pre-selected with the correct country that the user chose in the previous form.
In Your HTML you need to add country.iso instead of country
<select ng-model="userData.country"
ng-options="country.iso as country.name for country in countries">
</select>
And in your controller
$scope.userData = {"country":"DK"}; // this can be filled with prefilled data. which can be fetched from db or stored in a service
In case you want to save the whole object instead of just the iso code here is an example:
http://jsfiddle.net/2ES4t/
JS File:
$scope.countries = [{
iso: "DK",
name: "Danmark"
}, {
iso: "DE",
name: "Germany"
}];
$scope.userData = {};
$scope.userData.country = $scope.countries[0];
HTML File:
<select ng-model="userData.country" ng-options="country as country.name for country in countries"></select>
I would suggest storing the whole object, that you wouldn't have to search the country array later if you needed the name and only had the ISO code.
You probably are not filling the form in the Angular Way.
To do this, you should set the model (and the form will be pre-filled):
In your controller:
$scope.countries = [
{"iso":"DK","name":"Danmark"},
{"iso":"DE","name":"Germany"},
{"iso":"PT","name":"Portugal"},
{"iso":"CN","name":"Canada"}
];
$scope.userData = {};
$scope.userData.country = $scope.countries[3];
Fiddle
Try to change your html/angular to
<select ng-model="country"
ng-options="country.name for country in countries" ng-change="countryChanged(country)">
</select>
and your controller:
$scope.countryChanged = function(country){
$scope.userData.country = country
}

Categories