how to add a empty string as default in the drop down where dropdown is a directive - angularjs

In my AngularJS project, I am having a dropdown field as a directive and the values are coming from the backend.The user can also leave the field without selecting the dropdown(optional field) but the problem is, there is no empty field from the backend. So I need to add an empty field into the dropdown as default.
Since there is no option in the directive got struck in this issue.Googled a lot but didnt get any solutions yet.Kindly provide some suggestion.
Note:Client machine,cant post the code.

If there is no value set for the ng-model that the dropdown is bound to, Angular will provide a blank option by default that can be left in place (ignored) by the user and will result in your final value being whatever you set that ng-model to in the first place. If you need an actual empty string for the value, initialize it to that.
If you need to enable the user to select an empty value once they have already selected a value, you will need to add an empty value to the object that the dropdown is bound to. Add the empty value like this:
myPromise.then(function(data){
$scope.ddInfo = data;
$scope.ddInfo.unshift({id:'0000',text:'Not Applicable'});
});

Related

AngularJS: invalid input is not styled as invalid until I click on the input field and click out of it

I am setting input field to invalid from javascript like this:
$scope.formName.fieldName.$setValidity("string", false);
This is working, but it affects the view only after clicking in a input field and then clicking out of it.
How can I change it in order to see the invalid field immediatelly?
You'll need to attach an ng-change="checker(model)" to your input field. Then just apply an ng-class to it to check for formName.fieldName.$error.string (since you put string as the error key) or you can also do formName.fieldName.$invalid && !formName.fieldName.$pristine
I've attached this codepen for you to play around with and see how to apply an invalid class on the field without having to lose focus on it.
Hope that helps!

Validation Issue in IE 11 when same ng-model in multiple form set to required

The application I am working on has multiple tabs, each tab contains a form with ng-submit. And they share some common fields for example: selectedService.
It's been set to required in both forms. However updating it in one form then switch to another form, Chrome wouldn't complaint it's required since it already has value, however IE 11 complaints that it's required although it already has data entered and angular indicates that it's valid as well.
Is there anyway that I can update IE to let it know that this model has been updated and it has value? Or it's the form needs re-validation?
---------------------Update--------------
I am finally able to replicate it: http://plnkr.co/edit/Gjphya?p=preview
So if you select a value in the first dropdown and click submit in the second row, it says it's required. This only happens in IE, not in Chrome or other browsers.
And I think the problem is around this line:
$scope.selectedService = null;
Thanks!
All I need to fix is to add this line in the select tag:
<option value="">Please Select...</option>
If I init the ng-model in controller, it also fix the issue, however sometimes it causes unexpected issue if the dropdown is binded to an array instead of object collection.

AngularJS: why does my dropdown have an initial blank entry?

I am fetching some JSON frm a server and using it to populate a combobox.
A JSON entry looks like this
"campaign_id": "2",
"customer_id": "1",
"title": "Purple monkey dishwasher",
"description": "perfectly cromulent",
"start_time": "19/09/2015 09:42:06",
"end_time": "19/10/2015 09:42:06"
And I declare my drop down thus-wise
<select name="SelectCampaignForConnections"
ng-model="connectionsCampaignDropDown"
ng-options="campaign.title for campaign in campaigns"
ng-change="ShowConnectionsForCampaign(connectionsCampaignDropDown)">
I initialize the model of the select ...
$http.get(url)
.success(function(data, status, headers, config)
{
if ($scope.connections.length > 0)
$scope.connectionsCampaignDropDown = $scope.connections[0];
When the dropdown shows, it contains the title element of each JSON entry, BUT, it has an initial blank entry.
What am I doing wrongsomely?
[Update] #sheilak gave a good anser :
In order for the dropdown to defaulted to a non-blank value, the value
of the variable passed to ng-model must equal one of the options
passed to ng-options.
In your case where ng-options is populated by values of
campaign.title, it looks like the value passed to ng-model i.e.
connectionsCampaignDropDown should be populated with
$scope.connections[0].title rather than the whole object
$scope.connections[0].
$scope.connectionsCampaignDropDown = $scope.connections[0].title;
However, I would prefer to pass around an complete object, rather than just a field of it.
Can this be done?
(if not, then I will have to pass only the title to the ng-change function ShowConnectionsForCampaign() and it will then have to loop over the data to find a match, which seems inefficient)
<select name="SelectCampaignForConnections"
ng-init="justGiveItAName=getInitialSelection()"
ng-model="justGiveItAName"
ng-options="campaign.title for campaign in campaigns"
ng-change="ShowConnectionsForCampaign(justGiveItAName)">
where getInitialSelection() is a function on your scope that could take a param if you need it to, but I would probably go with something like this in the case you outline above:
function getInitialSelection() {return connections[0]};
or set it directly in the ng-init:
ng-init="$scope.connections[0]"
(you might have to fiddle with the above code - I haven't tested it).
btw - 'justGiveItAName' is then an object available elsewhere.
I have now tested it; see these Fiddles for working examples:
Setting directly in ng-init: http://jsfiddle.net/lukkea/nuo2c3Lk/
Using a function on the $scope: http://jsfiddle.net/lukkea/o6strxjf/
Passing the object instead of properties (as the OP requested): http://jsfiddle.net/lukkea/fsx8s67j/2/
Passing the objects in and object back: http://jsfiddle.net/lukkea/ww9yqsrm/3/
In order for the dropdown to defaulted to a non-blank value, the value of the variable passed to ng-model must equal one of the options passed to ng-options.
In your case where ng-options is populated by values of campaign.title, it looks like the value passed to ng-model i.e. connectionsCampaignDropDown should be populated with $scope.connections[0].title rather than the whole object $scope.connections[0].
$scope.connectionsCampaignDropDown = $scope.connections[0].title;
This should be possible, you just have to make sure that the initial value you set is the exact same object (not just another object with the same values)
You should be able to use campaign as campaign.title for campaign in campaigns in ng-options.
Then it stores the selected campaign object in the model (not just the value of campaign.title) and the label shown in the dropdown will still be campaign.title.
<select name="SelectCampaignForConnections"
ng-model="connectionsCampaignDropDown"
ng-options="campaign as campaign.title for campaign in campaigns"
ng-change="ShowConnectionsForCampaign(connectionsCampaignDropDown)">
The expression used here is: select as label for value in array.
select - the value stored in ng-model
label - the text displayed in the dropdown
The different expression options are listed in the official documentation.

AngularJS drop down (ng- options) not binding - string to object (initial selection)

I am having a problem binding data retrieved from the server to a drop down list. The main issue I think is the fact that the comparison is done on differing object types.
For example:
1. The object returned from the server contains a currency code string. we want this to be bound to an item in the dropdown list
"baseCurrencyCode":"GBP"
The view model returns the list of currencies.. These are returned as a list of currency objects with different properties
{"currencies":[{"id":1,"rateId":0,"abbreviation":"AFN","description":"Afghani","rate":0.0,"rateDescription":null,"languageCode":"en-gb","isDefault":true,"fullDescription":"AFN - Afghani - ","shortDescription":"AFN - Afghani"}}
etc.
Currently, I have got this working by writing a function to go through every property for every item in the list, find the correct property we wish to compare to - do the comparison and then return the initial selection.
When calling my save method I then need to manually bind the currency abbreviation to the object I wish to return to the server.
Surely there must be a better way to do this?
Some of my code for reference..
<select ng-model="selectedCurrency" ng-options="currency.shortDescription for currency in viewModel.currencies"></select>
// Call to my custom method..List, PropertyName, value to compare
$scope.selectedCurrency = InitialiseDropdown($scope.viewModel.currencies, "abbreviation", $scope.updatedObject.baseCurrencyCode);
// Code executed when saving - to bind the currency to the updated object
$scope.updatedObject.baseCurrencyCode = $scope.selectedCurrency.abbreviation;
Any help is appreciated!
EDIT
Sorry if I wasn't clear enough.. To summarise..
The main problem here is binding to the drop down and initial selection.
The object we are updating contains a parameter (string) of the currency abbreviation.
The list we select from is a list of currency objects. As these are two differing object types I have been unable to plug in angulars 2 way binding and have written some code to do this on initial retrieval and when saving.
The cleanest way to fix this would be to return a currency object in our retrieval instead of a simple string of the abbreviation, but this is not an option.
Is there a better way of enabling 2 way binding on different object types ?
Thanks again
It is not exactly clear what the problem is, but you can save yourself some work by binding the <select> to the currently selected currency object (so you don't have to look it up later).
select + ngOptions allow you to bind to one value while displaying another, with the following syntax:
<select ng-model="selectedCurrency"
ng-options="currency as currency.shortDescription
for currency in viewModel.currencies">
</select>
In the above example, $scope.selectedCurrency will be bound to the whole currency object, but currency.shortDescription will be displayed in the dropdown.
See, also, this short demo.
UPDATE:
In case you don't need to bind to the whole currency object, but just bind updatedObject's baseCurrencyCode property to the abbreviation of the selected (in dropdown) currency, you can do it like this:
<!-- In the VIEW -->
<select ng-model="updatedObject.baseCurrencyCode"
ng-options="c.abbreviation as c.shortDescription
for c in currencies">
</select>
// In the CONTROLLER
$scope.currencies = [...];
$scope.updatedObject = {
...
baseCurrencyCode: <baseCurrencyCodeFromServer>
};
See, also, that short demo.
I have had the same problem, ng-model and ng-option being from 2 different sources. My ng-model is bound to a value in a json object representing a chosen filename and my ng-option is a list of possible values taken from a csv file.
In the controller I am reading a directory via a Nodejs route, and creating a json array of filenames like this
var allCsvFiles = [{"name":"file1.csv"},{"name","file2.csv},etc..]
The current csv file, i.e. the selected one is stored in another json array
[{"date":"01-06-2017","csvfile":"file1.csv","colour":"red"},{...}, etc].
I was using the following code for the dropdown:
<select type="text" ng-model="file.csvfile"
ng-options="opt.name for opt in allCsvFiles track by opt.name"></select>
Which caused the current selection to be blank and if I selected an item from the dropdown it put [object],[object] as the current selection. If I stepped through the code I found that it seemed to be selecting {"name","file1.csv"} as the option and couldn't display it, this seemed odd as my ng-options selection looks like it should just return the value of "name" not the array entry. I tried many different ways to make this work but eventually I found that if I made the list of possible selections a plain javascript array:
var allCsvFiles = ["file1.csv","file2.csv", "file3,csv]
and changed the select to:
<select type="text" ng-model="file.csvfile" ng-options="opt for opt in allCsvFiles"></select>
then the dropdown selection worked as expected.
I may have missed some other obvious solution here, but as the array of json objects is one dimensional anyway it doesn't seem to be an issue.
It looks like the OPs question has been answered, I just thought I'd add this as it solved it for me.

ng-options creates an empty option at the end when listbox group heading is clicked

I am stuck on this particular issue with ng-options. I am creating a listbox with option grouping:
<select ng-model="selTemplates" size="3" style="width: 150px"
ng-options="template.Name group by template.Type for template in userTemplates">
</select>
When I click on a group heading (Type1 or Type2), Chrome creates an empty option at the end and marks it selected. I believe it has something to do with the selection because it may not find anything 'selected' when a header is clicked, but an empty value at the bottom is not desired.
Please see the fiddle here.How can i fix it?
(The code works fine in IE9, although not sure why the fiddle doesn't)
ng-options adds empty option if case if value currently bound by ng-model doesn't exist in list of options. This prevents from overwriting value due bounding to empty select (this is an often problem in for example knockoutjs).
Clicking option group clears selection and empty option added.
You can see it if add debug <div>{{selTemplates}}</div> below select list.
Also even static select with size or multiple attribute specified clears its selection on clicking option. If size is omitted (for regular dropdown) clicking optgroup doesn't clears selected value.
I'm not sure if this browser inconsistence or expected behavior (if you said it works in IE) but consider replacing select with custom HTML emulates list selection.
Looks like inconsistent browser implementation is the reason. On clicking option header, Chrome clears out the selection whereas IE doesn't, that's why Chrome inserts a new empty row at the bottom.
As a workaround, I am saving last selected value in a variable, and in case user clicks on header (which will make selection null), I am restoring the last selection. See fiddle. Not exactly pretty, but gets the work done.
$scope.checkSelection = function() {
if ($scope.selTemplates == null) {
$scope.selTemplates = last;
}
else {
last = $scope.selTemplates;
}
}
Add ng-init="selTemplates=userTemplates[0]" in your <select>
You can remove "$scope.selTemplates = ***" in your controller

Resources