I want to do only one checkbox selected at a time in ngFor in angular 5.
i have the following code below.
<div class="form-check" style="margin-top:0;">
<label class="form-check-label">
<input class="form-check-input" id="res{{restaurant._id}}" (change)="selectRestaurant(restaurant,i)" [checked]="restaurant.checked" type="checkbox">
<span class="form-check-sign"></span>
</label>
</div>
And in my component
selectRestaurant(restaurant: any, i: any) {
if (restaurant) {
restaurant.checked = !restaurant.checked;
}
}
So any possible solution for only one checkbox selected in given list?
You have to bind the checkbox item with ngmodel to the specific instance in for loop.
This you can try with ReactiveForms. See one example https://stackblitz.com/angular/ayqnbvbkmpy
I saw many examples with loop using. But I`am think its bad idea when checkboxes are too many. I recommend to use another way.
Create variable to contain checkbox index.
public checkboxIndex = 0; //default value for checking
public checkboxModel = [];
ngOnInit() {
for (let i = 0; i < checkboxCount.length; i++) {
this.checkboxModel.push({ name: `${i}`, enabled: false });
}
public checkboxChange(index) {
if (this.checkboxIndex !== index) {
this.checkboxModel[this.checkboxIndex].enabled = false;
}
this.checkboxIndex = index;
}
//HTML
<div *ngFor="let checkbox of checkboxCount.length; let i = index">
<input type="checkbox" [(ngModel)]="checkboxModel[i].enabled"
name="checkboxModel[i].name"
(change)="checkboxChange(i)"> </input>
</div>
It should help. Please correct me if I made some mistakes.
So this works with static data, but when I push data with a $http this autocomplete does not work. The data pushes to the empty array of airport_list but something is happening when I try to use airport_list in for the autocomplete. Not sure what is is. I can only find answers which pertain to static data.
This is updated per everyones help.
Here is the controller
app.controller('selectCtrl', function($scope, $http) {
$scope.airport_list = null;
$http({
url: 'someUrl.com',
method: 'GET'
})
.then((response) => {
angular.forEach(response.data.airports, function(value, key) {
$scope.airport_list = response.data.airports;
})
$scope.airports = $scope.airport_list;
});
$scope.selectAirport = function(string) {
$scope.airport = string;
$scope.hidelist = true;
};
})
Here is the template
<div class="control">
<div>
<input
type="text"
name="airport"
id="airport"
ng-model="airport"
ng-change="searchFor(airport)"
placeholder="From..."
/>
<div class="airport-container-dropdown" ng-hide="hidelist">
<div
class="airport-list"
ng-repeat="airport in airports"
ng-click="selectAirport(airport)"
>
{{ airport.name }}
</div>
</div>
</div>
</div>
I really would like to do this without using bootstrap typeahead.
Thank you for looking at this.
I have made changes as recommended by below answers and the $http request is feeding into the autocomplete as a whole list but searching by name does not work and clicking on name sets [object, object]
this would be the code which is specific to that functionality.
$scope.searchFor = function(string) {
$scope.hidelist = false;
const output = [];
angular.forEach($scope.airport_list, function(airport) {
if (airport[0].toLowerCase().indexOf(string.toLowerCase(airport)) >=
0) {
output.push(airport);
}
});
$scope.airports = output;
};
$scope.selectAirport = function(string) {
$scope.airport = string;
$scope.hidelist = true;
};
Try this:
$scope.airport_list = response.data.airports;
What I am seeing is that you have an array: $scope.airport_list = [];
When you make your http request, you push what I would understand to be an array of airports into that array. So you end up with your airport array from the backend at the first position of $scope.airport_list, vs. $scope.airport_list being the actual list.
For your search method, you should change the following:
In your HTML:
ng-change="searchFor(airport.name)"
In your JS:
I've renamed your function and changed the input variable to be more clear. You were passing in a full airport, but treating it as a string. You need to compare your provided airport name to that of the airports in the array. So you iterate over the array, and compare each element's name property to what you pass in.
$scope.searchFor = function(airportName) {
$scope.hidelist = false;
const output = [];
angular.forEach($scope.airport_list, function(airport) {
if (airport.name.toLowerCase() === airportName) {
output.push(airport);
}
});
$scope.airports = output;
console.log($scope.airports);
};
I have provided minimal changes to your code to implement this, however I suggest you look at this SO post to filter drop down data more appropriately.
Angularjs Filter data with dropdown
If you want to simply filter out what is displayed in the UI, you can try this in your HTML template. It will provide a text field where you supply a partial of the airport name. If at least one character is entered in that box, the list will display on the page, with the appropriate filtering applied. This will avoid having to call functions on change, having a separate array, etc.
<input type="text" name="airport" id="airport" ng-model="airportSearch.name" placeholder="From..." />
<div class="airport-container-dropdown" ng-hide="!airportSearch.name">
<div class="airport-list"
ng-repeat="airport in airport_list | filter:airportSearch"
ng-click="selectAirport(airport)">
{{ airport.name }}
</div>
</div>
I'm trying to use filter who gonna change depending on a click or write on an input.
<input
name="hotelinput"
type="text"
ng-keydown="changeFilterToKeyPressed()"
ng-click="changeFilterToClicked()">
<div ng-repeat="hotel in filteredHotels = (hotels | VARIABLEFILTER | orderBy: 'country') track by $index">
...
</div>
I know that you can do filter:variable and change it in the controller but I need to change the full filter for one of my custom filters every time.
I didn't tested it but something like this could be possible
JS
if(x){
$scope.VARIABLEFILTER = $filter('myCustomFilter')
} else {
$scope.VARIABLEFILTER = $filter('myCustomFilter2')
}
I made it to work and rewrote the filter I once did in other question
http://plnkr.co/edit/LuA3hYr7mImihYnVIxqQ
.filter('applyFilter', function($filter) {
return function(input, filterToApply) {
return filterToApply === undefined ? input : $filter(filterToApply)(input)
}
})
I hope that's what you were looking for
You need ngChange instead of ngClick
<input
name="hotelinput"
type="text"
ng-model="filterKey"
ng-change="changeFilterToKeyPressed()"
ng-focus="changeFilterToClicked()">
and update your function changeFilterToKeyPressed
$scope.changeFilterToKeyPressed = function() {
$scope.VARIABLEFILTER = someUpdatesWhichYouWant($scope.filterKey); //You can use filterKey on any change
}
I have a json record as country, inside country, it contains many states, I want to filter by either label or value, so the states json looks like:
$scope.states: {"s1":{"label":"Alabama","value":"Alabama"},"s2":{"label":"Alaska","value":"Alaska"},"s3":{"label":"Arizona","value":"Arizona"},"s4":{"label":"Arkansas","value":"Arkansas"},"s5":{"label":"California","value":"California"},"s6":{"label":"Colorado","value":"Colorado"},"s7":{"label":"Connecticut","value":"Connecticut"},"s8":{"label":"Delaware","value":"Delaware"},"s9":{"label":"DC","value":"DC"},"s10":{"label":"Florida","value":"Florida"},"s11":{"label":"Georgia","value":"Georgia"},"s12":{"label":"Hawaii","value":"Hawaii"},"s13":{"label":"Idaho","value":"Idaho"},"s14":{"label":"Illinois","value":"Illinois"},"s15":{"label":"Indiana","value":"Indiana"},"s16":{"label":"Iowa","value":"Iowa"},"s17":{"label":"Kansas","value":"Kansas"},"s18":{"label":"Kentucky","value":"Kentucky"},"s19":{"label":"Louisiana","value":"Louisiana"},"s20":{"label":"Maine","value":"Maine"},"s21":{"label":"Maryland","value":"Maryland"},"s22":{"label":"Massachusetts","value":"Massachusetts"},"s23":{"label":"Michigan","value":"Michigan"},"s24":{"label":"Minnesota","value":"Minnesota"},"s25":{"label":"Mississippi","value":"Mississippi"},"s26":{"label":"Missouri","value":"Missouri"},"s27":{"label":"Montana","value":"Montana"},"s28":{"label":"Nebraska","value":"Nebraska"},"s29":{"label":"Nevada","value":"Nevada"},"s30":{"label":"New Hamshire","value":"New Hamshire"},"s31":{"label":"New Jersey","value":"New Jersey"},"s32":{"label":"New Mexico","value":"New Mexico"},"s33":{"label":"New York","value":"New York"},"s34":{"label":"North Carolina","value":"North Carolina"},"s35":{"label":"North Dakota","value":"North Dakota"},"s36":{"label":"Ohio","value":"Ohio"},"s37":{"label":"Oklahoma","value":"Oklahoma"},"s38":{"label":"Oregon","value":"Oregon"},"s39":{"label":"Pennsylvania","value":"Pennsylvania"},"s40":{"label":"Puerto Rico","value":"Puerto Rico"},"s41":{"label":"Rhode Island","value":"Rhode Island"},"s42":{"label":"South Carolina","value":"South Carolina"},"s43":{"label":"South Dakota","value":"South Dakota"},"s44":{"label":"Tennessee","value":"Tennessee"},"s45":{"label":"Texas","value":"Texas"},"s46":{"label":"Utah","value":"Utah"},"s47":{"label":"Vermont","value":"Vermont"},"s48":{"label":"Virgin Islands","value":"Virgin Islands"},"s49":{"label":"Virginia","value":"Virginia"},"s50":{"label":"Washington","value":"Washington"},"s51":{"label":"West Virginia","value":"West Virginia"},"s52":{"label":"Wisconsin","value":"Wisconsin"},"s53":{"label":"Wyoming","value":"Wyoming"}}
the code for the page is:
<label class="item item-input">
<input type="text" placeholder="请输入你要寻找的省市" ng-model="searchText.$"/>
</label>
<ion-radio ng-model="create.state" ng-repeat="s in states | filter:searchText)" ng-value="s">{{s.label}}</ion-radio>
this does not work, I also tried custom filter based on another post: filter on nested objects, does not work for me
mention which field are you trying to put a filter on
filter:{'label': searchText} and ng-model="searchText" would suffice.
As you are trying to iterate over the object properties you can define a custom filter as follows .Here is the working example
.filter('customFil', function () {
return function (p, query) {
var obj = {};
for (var key in p) {
if (p.hasOwnProperty(key)) {
if (p[key].label.includes(query)) {
obj[key] = p[key];
}
}
}
return obj;
}
});
I have a large amount of code that I inherited. It is working according to the original spec, so although it may or may not be the "right" way of doing things, it does work and I'd prefer not to mess with it. (I am VERY new to angular, and under a tight deadline - I don't have time right now to "fix" things that aren't broken, even if they're not being done the "correct" way.)
I have a checkbox and a group of address fields. When the checkbox is checked, a function runs that populates the address fields.
<input id='as_check' type="checkbox" ng-model='model.prepop_addr' ng-change="model.handlePrepopAddress()">
<input type="text" placeholder="Address 1" required ng-model='model.payment.addr1'/>
<input type="text" placeholder="Address 2" ng-model='model.payment.addr2'/>
<input type="text" placeholder="City" required ng-model='model.payment.city'/>
<input type="text" placeholder="State" required ng-model='model.payment.state'/>
<input type="text" placeholder="Zip" required ng-model='model.payment.zip'/>
In my controller, I have a function called handlePrepopAddress():
model.handlePrepopAddress = function () {
if (model.prepop_addr) {
console.log("prepop is true");
var del_addr = $window.user_state.deliveryAddress;
model.payment.addr1 = del_addr.address;
model.payment.addr2 = null;
model.payment.city = del_addr.city;
model.payment.state = del_addr.state;
model.payment.zip = del_addr.zip;
} else {
console.log("prepop is false");
model.payment.addr1 = null;
model.payment.addr2 = null;
model.payment.city = null;
model.payment.state = null;
if (!model.payment.saved) {
model.payment.zip = null;
}
}
return true;
};
When I click the checkbox, this runs correctly and updates the various fields. Requirements have changed, and the client now wants the checkbox defaulted to checked, which would then default the values of the fields. Rather than duplicating code, I thought I'd be able to just run the function at the start of the controller, like this:
place_order.controller('AsCreditCardCtrl', ['$scope', 'PaymentModel', function ($scope, model) {
$scope.model = model;
model.prepop_addr = true;
model.handlePrepopAddress();
}]);
The function is running, as the console.log statements I have in the function are running. But the view is not updating; the checkbox is visibly unchecked and the fields are empty aside from the initial placeholder values.
What am I missing? How can I make the function update the view?
You can try
var i= model.handlePrepopAddress();
It might work.