ng-repeat show default empty value for first option - javascript

The ng-repeat show default empty string for first option. Why in may case it does not work. What is wrong in here?
My angular code is here. What i mistake here. I don't understand.
var exchange = angular.module('app', []);
exchange.controller('ExchangeController', ExchangeController);
function ExchangeController($scope, $http) {
$http
.get(window.location.origin + "/api/get-item/", {
transformRequest: angular.identity,
headers: {'Content-Type': undefined, 'Process-Data': false}
})
.then(function(response){
$scope.items = response.data.items;
$scope.send_item_id = $scope.items[0].value;
});
$scope.getSendItem = function() {
var send_item_id = $("#send_item_id").val();
console.log(send_item_id);
}
}
Here is my html code,
<div class="form-group">
<div class="col-md-12 col-sm-12">
<select data-plugin-selectTwo
name="send_item_id"
id="send_item_id"
ng-model="send_item_id"
ng-change="getSendItem()"
class="form-control populate">
<option ng-repeat="item in items" value="#{{ item.value }}">#{{ item.text }}</option>
</select>
</div>
</div>

You need to manually select a "selected" item (itemSelected model in my solution) and change your value attribute to ng-value to make it work in the AngularJS way. Please check this demo fiddle I've created for you. Btw. you don't need jQuery here: please check how I log the selected item in getSendItem(). This will work for AngularJS 1.6.x or later.
View
<div ng-controller="MyCtrl">
<select data-plugin-selectTwo
name="send_item_id"
id="send_item_id"
ng-model="itemSelected"
ng-change="getSendItem()"
class="form-control populate">
<option ng-repeat="item in data" ng-value="item.value">
#{{ item.text }}
</option>
</select>
</div>
AngularJS application
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.data = [{
"text": "Bkash",
"value": 1
}, {
"text": "Paypal",
"value": 2
}];
$scope.itemSelected = $scope.data[0].value;
$scope.getSendItem = function() {
console.log($scope.itemSelected);
}
});
While using AngularJS 1.5.x or earlier you need to do it like in this demo fiddle by using ng-selected:
View
<div ng-controller="Controller">
<select name="send_item_id"
id="send_item_id"
ng-model="itemSelected"
ng-change="getSendItem()">
<option
ng-repeat="item in data" value="{{ item.value }}"
ng-selected="{{item.value === itemSelected}}">
{{ item.text }}
</option>
</select>
</div>
AngularJS application
var myApp = angular.module('app', []);
myApp.controller('Controller', function($scope) {
$scope.data = [{
"text": "Bkash",
"value": 1
}, {
"text": "Paypal",
"value": 2
}];
$scope.itemSelected = String($scope.data[0].value);
console.log($scope.itemSelected);
$scope.getSendItem = function() {
console.log($scope.itemSelected);
}

You need to match the option value and ng-model value in order to prevent the default empty space. in your case it does not match since there is # symbol in front of your option value. remove it.
<option ng-repeat="item in items" value="{{ item.value }}">#{{ item.text }}</option>

Try this. It's working for me.
<option value="{{item.value}}" ng-repeat="item in items" ng-selected="$first">{{ item.text }}</option>

Related

Using AngularJs component mutiple times in ng-repeat

I have a drop down component in angularjs which when used single time works fine and the values are selected but if I use the same component multiple times in ng-repeat the drop downs are rendered but the values are not being selected. I am using the following code:
JS file:
angular.module('mainApp').component('inputSelectComponent', {
templateUrl : 'sys/templates/input-select.template.html',
bindings : {
ngModel : '='
},
controller: ['$scope', '$element', '$http', 'translate', 'apiServer', 'session', 'EVENTS', function compCategoriesDropdownController($scope, $element, $http, translate, apiServer, session, EVENTS) {
var _select = $element.find('select');
$scope.options = JSON.parse($element.attr('options'));
setTimeout(function(){
$element.find('select').selectize({});
}, 0);
$scope.$watch('$ctrl.ngModel', function(e){
var selectize = _select[0].selectize;
if (typeof(selectize) !== 'undefined') {
setTimeout(function(){
selectize.setValue(e);
}, 0);
}
});
$scope.$watch('$element.attr', function(e){
$scope.label = $element.attr('label');
if ($element.attr('disabled') === 'disabled'){
_select.attr('disabled', 'disabled');
}
});
$element.find('select').on('change', function(e){
$scope.$ctrl.ngModel = e.target.value;
});
}]
});
Template file:
<label class="col-form-label">{{label}}</label>
<select class="cat-drop{{(error!=null)? ' not-validated' :''}}">
<option ng-repeat="(key, value) in options" value="{{key}}">
{{value}}
</option>
</select>
This is how I am calling it:
<div ng-repeat="relatedproduct in relatedproductsData">
<span class="serial-number">{{ $index + 1 }}.</span>
<div class="form-group row">
<input-select-component ng-model="relatedproduct.item_type" class="input-component col-sm-2" label="{{t('related_products_item_type')}}" options='{"2": "2 - For Product", "3": "3 - For Category"}'></input-select-component>
</div>
</div>
Any help is appreciated!
I used a directive instead of an component.
The documentations says:
Components only control their own View and Data: Components should never modify any data or DOM that is out of their own scope. ..
Using a directive allows you to usa ng-model="ngModel" on the select component in the directive and change the value directly.
angular.module('mainApp').directive('inputSelectComponent', function () {
return {
template: `<label class="col-form-label">{{label}}</label>
<select class="cat-drop{{(error!=null)? ' not-validated' :''}}" ng-model="ngModel">
<option ng-repeat="(key, value) in options" value="{{key}}">
{{value}}
</option>
</select>`,
scope: {
ngModel: '=',
options: '=',
}
}
});
it does work in the caller:
<div ng-repeat="relatedproduct in [{ item_type : '' }, {item_type : ''}, { item_type: '' }]">
<span class="serial-number">{{ relatedproduct }}.</span>
<div class="form-group row">
<input-select-component ng-model="relatedproduct.item_type"
class="input-component col-sm-2"
label="{{t('related_products_item_type')}}"
options='{"2": "2 - For Product", "3": "3 - For Category"}'></input-select-component>
</div>
</div>
Good luck!
Try using $timeout instead of setTimeout. Maybe because of angularJS digest...

Pre-Select the only item in dropdown AngularJS

I am trying to create an attribute directive (because I need to use this logic at multiple places in my project) for Select dropdown which automatically selects the only item if the items array has only one element.
I have the following HTML with an attribute directive named smart-select-dropdown:
<select class="form-control" ng-model="selectedItem" smart-select-dropdown
ng-options="item as item.name for item in items | filter: {someFilter}">
<option value="" ng-bind="Select Item"></option>
</select>
Here is my directive code:
angular.module('app').directive('smartSelectDropDown', function(){
return{
restrict: 'A',
replace: true,
link: function(scope, element){
angular.element(document).ready(function () {
if(element[0].options.length === 2){
element.find('select option:nth-child(2)').prop('selected', true);
}
});
}
}
});
Here is the controller code:
angular.module('app').controller('MyCtrl', function($scope){
$scope.selectedItem = null;
$scope.items = [
{
id : 1,
name : 'Item 1'
},
{
id : 2,
name : 'Item 2'
},
{
id : 3,
name : 'Item 3'
}
];
});
The problem I am facing is that element[0].options.length is not giving me the correct length. It is always giving me 1 which is actually the default 'Select Item' option. It does not contain the length of ng-options which is actually required. Can anyone let me know what am I missing here?
PS: I am using AngularJS version 1.2.17
This can be achieved without a directive.
Controller Code changes:
angular.module('app').controller('MyCtrl', function($scope){
$scope.items = [
{
id : 1,
name : 'Item 1'
},
{
id : 2,
name : 'Item 2'
}
]
});
$scope.selectedItem = items[1]; // or items[0] as per your requirement
HTML Code Changes:
<select class="form-control" ng-model="selectedItem"
ng-options="item as item.name for item in items track by item.id">
<!-- You may choose to remove this first option tag with in select -->
<option value="" ng-bind="Select Item"></option>
</select>
There is even no need of a directive in your case, you can just check the $scope.items length and assign the first element to ng-model if its length is 1
Controller:
angular.module('app').controller('MyCtrl', function($scope){
$scope.selectedItem = null;
$scope.items = [
{
id : 1,
name : 'Item 1'
},
{
id : 2,
name : 'Item 2'
}
]
if($scope.items.length == 1){
$scope.selectedItem = $scope.items[0];
}
});
HTML:
<select class="form-control" ng-model="selectedItem" ng-options="item as item.name for item in items">
<option value="" ng-bind="Select Item"></option>
</select>
You can get the selectedItem and items from the controller to your directive scope, and check the condition and set selectedItem accordingly.
angular.module('app').directive('smartSelectDropDown', function(){
return{
restrict: 'A',
replace: true,
scope: {
items: '=',
selectedItem: '=selectedItem'
}
link: function(scope){
if(scope.items.count == 1){
scope.selectedItem = scope.items[0];
}
}
});
}
}
});
Though, you might have to modify the code for some corrections as I have not tested it.
Note: if you are using directive just for this purpose, then follow #Rangamannar answer.

trigger an angular function when option selected from drop down

I am populating a select dropdown menu by making a call to an api. When the user chooses an option from the select menu I wish to fire the second function - $scope.getRoles(). However, this is firing immediately. Any ideas why this is happening? Please see my attempted code below.
html
<select>
<option ng-change="getRoles()" ng-repeat="country in countries">{{ country.countryCode }}</option>
</select>
angular
app.controller("jobsCtrl", function($scope, careerData) {
//get list of countries when app loads
careerData.countryList().then(function successCallback(response) {
$scope.countries = response.data;
$scope.countries.unshift({countryCode: "Select a country"});
}, function errorCallback(response) {
console.log(response);
});
$scope.getRoles = careerData.jobByCountry().then(function successCallback(response) {
console.log(response)
}, function errorCallback(response) {
console.log(response);
})
});
app.factory('careerData', ['$http', function($http){
return {
countryList: function() {
return $http({
method: 'GET',
url: 'testUrl'
})
},
jobByCountry: function() {
return $http({
method: 'GET',
url: 'someurl'
})
}
}
}]);
First you should use ngOptions.
Change this:
<select>
<option ng-change="getRoles()" ng-repeat="country in countries">{{ country.countryCode }}</option>
</select>
for:
<select ng-options="country as country.countryCode for country in countries" ng-model="countrySelected" ng-change="getRoles()">
</select>
Example:
angular.module('app', [])
.controller('mainCtrl', function($scope) {
$scope.cars = ["Audi", "BMW", "Corolla", "Mercedes"];
$scope.check = function() {
console.log($scope.car);
}
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl">
Cars:
<select ng-model="car" ng-options="car for car in cars" ng-change="check()">
<option value="">Select a car</option>
</select>
</body>
</html>
so I think you were looking for this
(ngModelChange)="getRoles()"
in your HTML tag.
this will fire when you change the module it works for most input field I came across here because it doesn't work with mat-select.
this is for angular 7. this is also an old question.
comment:
but I hope this will help you because this is still not answered if the previous answer works accept it.

Two way binding of select input in a directive not working

I've created a directive for a select input to select a userId. The model binds from the directive to the rest of the view. However, when I set the id from the controller it doesn't seem to bind to select input in the directive.
Controller:
app.controller('MainCtrl', function($scope) {
// set userId to willem's Id
$scope.userId = 3;
});
Directive:
app.directive('selectUser', function() {
return {
restrict: 'E',
scope: {
ngModel: '='
},
controller: function($scope) {
$scope.users = [{
"id": 1,
"name": 'Tupac'
}, {
"id": 2,
"name": 'Biggie'
}, {
"id": 3,
"name": 'Willem'
}];
},
templateUrl: 'directive.html'
};
});
index.html
<body ng-controller="MainCtrl">
users:
<select-user ng-model="userId"></select-user>
userId = {{userId}}
</body>
directive.html
<select class='form-control focus' ng-model="ngModel">
<option value="">all users</option>
// doesn't bind from the controller. Supposed to show willem, instead of all users to start with.
<option ng-Repeat="user in users" value="{{user.id}}">{{user.name}}</option>
</select>
Working example on: http://plnkr.co/edit/c7eyoB
You should use ngOptions :
<select class='form-control focus' ng-model="ngModel" ng-options="user.id as user.name for user in users">
<option value="">all users</option>
</select>
Then the binding will work. See updated plnkr
Edit, concerning the following question in comment :
could you please explain, why it is not working with ng-repeat?
You can achieve the same visual result with :
<select class='form-control focus' ng-model="ngModel">
<option value="">all users</option>
<option ng-repeat="user in users" value="{{user.id}}" ng-selected="user.id === ngModel">{{user.name}}</option>
</select>
I.e. we added ng-selected="user.id === ngModel".
But this has some drawbacks. First, you are creating unneeded isolated scopes. And also, the values bound to the options are strings, i.e. you will actually select '1', '2' or '3' instead of 1, 2 or 3.

AngularJS dynamically populate details from json based on item selected

I am trying to create a page where you have few items in a list group which when selected should show more details.
Please view the example here http://plnkr.co/edit/Oava3pA9OTsm80K58GdT?p=preview
How can I populate the details from the json file based on the item that is selected in the list group?
This is what I have so far.
html:
<div ng-controller=ItemsController>
<h3>Test</h3>
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">
<ul class="list-group">
<a class="list-group-item" ng-repeat="item in itemDetails">{{item.name}}</a>
</ul>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<h2>Name: </h2>
<br />Address Line 1:
<br />Address Line 2:
<br />Suburb:
<br />Phone:
<br />Email:
</div>
</div>
</div>
</div>
script:
var myItemsApp = angular.module('myItemsApp', []);
myItemsApp.factory('itemsFactory', ['$http', function($http){
var itemsFactory ={
itemDetails: function() {
return $http(
{
url: "mockItems.json",
method: "GET",
})
.then(function (response) {
return response.data;
});
}
};
return itemsFactory;
}]);
myItemsApp.controller('ItemsController', ['$scope', 'itemsFactory', function($scope, itemsFactory){
var promise = itemsFactory.itemDetails();
promise.then(function (data) {
$scope.itemDetails = data;
console.log(data);
});
}]);
json:
[
{
"$id":"1",
"name":"Test itemName 1",
"themeName":"ASD",
"addressLine1":"18 Banksia Street",
"addressLine2":null,
"suburb":"Heidelberg",
"state":"VIC",
"postalCode":"3084",
"contactPhone":"+61 3 123456",
"emailAddress":"qwerty.it#xyz.com"
},
{
"$id":"2",
"name":"Test itemName 2",
"themeName":"WER",
"addressLine1":"11 Riverview Place",
"addressLine2":"Metroplex on Gateway",
"suburb":"Murarrie",
"state":"QLD",
"postalCode":"4172",
"contactPhone":"1300 73123456",
"emailAddress":"asdfg.it#xyz.com"
},
{
"$id":"3",
"name":"Test itemName 3",
"themeName":"ERT",
"addressLine1":"60 Waterloo Road",
"addressLine2":null,
"suburb":"North Ryde",
"state":"NSW",
"postalCode":"2113",
"contactPhone":"123456",
"emailAddress":"zxcvb.it#xyz.com"
}
]
Any help would be greatly appreciated.
I am very new to programming. Please also feel free to alternative ways of achieving this if I have done it wrong.
You can use the ng-click directive to specify what happens when you click something.
So I made it assign the clicked item to the $scope.selected object using a function ($scope.select(item)) and then I bound the properties of that object to your little details section. That's probably the simplest way to do it.
Ctrl
$scope.select = function(item) {
$scope.selected = item;
}
$scope.selected = {};
HTML
<a class="list-group-item" ng-click="select(item)" ng-repeat="item in itemDetails">
{{item.name}}
</a>
And the selected object is then available like this:
<h2>Name: {{selected.name}}</h2>
etc...
See my example here: http://plnkr.co/edit/mUMZ0VGO8l1ufV1JJNQE?p=preview

Categories

Resources