AngularJS select required - javascript

I'm having some issues with setting up the validation for a select. the code reads like
HTML
<form name="customerForm" novalidate="novalidate" data-ng-submit="submit()">
<li class="has-error" data-ng-if="customerForm.country.$error.required">
{{ 'CountryRequired' | translate }}
</li>
<label for="ddlCountries">{{ 'Country' | translate }}</label>
<select id="ddlCountries" name="country" class="form-control"
data-ng-model="selectedCountry"
data-ng-options="option.text for option in countries track by option.id"
data-ng-change="countryChange()" required="required">
<option value="" selected="selected">{{ 'SelectCountry' | translate }}</option>
</select>
</form>
JS Controller
$scope.countries = [];
countryService.getCountries().then(function (results) {
$scope.countries = results.data;
}, function (error) {
console.log(error.data.message);
});
$scope.$watch('customer.country', function (id) {
// Select the value on the dropdown list
$scope.selectedCountry = { id: id };
});
$scope.countryChange = function () {
$scope.customer.country = $scope.selectedCountry.id;
};
$scope.submit = function () {
if ($scope.customerForm.$valid) {
customerService.postCustomerForm($scope.customer).success(
function (data, status, headers, config) {
/*success callback*/
}).error(function (data, status, headers, config) {
alert("Submitting form failed!");
});
} else {
console.log("Invalid fields");
}
};
I've tried different things like setting selected="selected" on the select but didn't work. Also tried required and ng-required without luck.
Am I missing something or doing it wrong?

The problem is that you reset select model so original one you defined is replaced with a new one. Look at this piece of code:
$scope.$watch('customer.country', function(id) {
$scope.selectedCountry = {id: id};
});
In this code you overwrite $scope.selectedCountry with totally new object, so the model which has been used for setting up form validation is destroyed and new validation is never build.
In your case you can update selectedCountry model like this:
$scope.$watch('customer.country', function(id) {
if (id) {
$scope.selectedCountry.id = id;
}
});
But better, remove wather all together, you don't need it since you have ngChange directive, where you can update selectedCountry.id.
Demo: http://plnkr.co/edit/CXDRdRYxZn38FnanOqid?p=preview

Related

Fetch input value after Dropdown menu item selected

I have a table about products. It has id, productdmc, productcode columns.
In this select menu, productdmc is showing.
When one item was selected, label its gonna change with related rows. Thats what i need. But i cant figure out the solution.
productcode.
<select class="form-control" name="productdmc" id="productdmc">
<option disabled selected>DMC</option>
#foreach ($product as $products)
<option value="{{ $products->productdmc }}">{{ $products->productdmc }}</option>
#endforeach
</select>
Related input
<input type="text" name="productcode" id="productcode">
This is the js code. I dont know this is working. This is my actual problem.
<script type="text/javascript">
$(document).ready(function() {
$('select[name="productdmc"]').on('change', function() {
var tmp = $(this).val();
if(tmp) {
$.ajax({
url: '/products/create/'+tmp,
type: "GET",
dataType: "json",
success:function(data) {
$('productcode').empty();
$.each(data, function(key, value) {
$('productcode').innerHTML('<input value="'+ key +'">');
});
}
});
}else{
$('productcode').empty();
}
});
});
</script>
In my Controller:
$val = DB::table("products")->pluck("productdmc","productcode");
return json_encode($val);
I know, i messed up so much. But codes are so complicated than this. I write this code in here(shorter version). Not copy-paste. I stucked here in a while. I cant find what is the real solution is.
I am open for all kinda solution.
Sorry for my bad english.
innerHTML is a property of HTML elements, not a function of jQuery's representation.
Use html(content) instead, and I think it should work:
$('#productcode').html('<input value="'+ key +'">');
Your selector is wrong, you forgot the '#'.
var $productCode = $('#productcode');
Also, when the event 'change' is triggered, you need to fetch the selected option.
var selectedValue = $element.find('option:selected').val();
HTML
<select class="form-control" name="productdmc" id="productdmc">
<option disabled selected>DMC</option>
#foreach ($product as $products)
<option value="{{ $products->productdmc }}">{{ $products->productdmc }}</option>
#endforeach
</select>
<input type="text" name="productcode" id="productcode">
Javascript:
<script type="text/javascript">
$(document).ready(function() {
$('body').on('change', 'select[name="productdmc"]', function(e) {
var $element = $(e.currentTarget); // $(this) is also fine.
// Get selected value
var selectedValue = $element.find('option:selected').val();
var $productCode = $('#productcode');
// No value selected
if (!selectedValue) {
$productCode.val('');
return;
}
$.ajax({
url: '/products/create/' + selectedValue,
type: 'GET',
dataType: 'json',
error: function() {
$productCode.val('');
},
success: function(res) {
$productCode.val('');
if (res.length < 1) return;
$productCode.val(res[0] || '');
// This will populate more than 1 field. So,
// I'm not sure about what you expect on the backend.
// If you want to populate more than 1,
// you should change the selector/field (do not use id in this case)
// $.each(res, function(key, value) {
// $productCode.val(key);
// });
}
})
});
});
</script>
PHP
<?php
$products = DB::table('products')->get();
return response(
$products->pluck('productdmc', 'productcode')->toArray()
);
You can read more about jQuery selectors here: https://api.jquery.com/category/selectors/

Get id and a field value in EasyAutocomplete plugin

Using easyAutocomplete plugin, I autocomplete an input field and take the selected value and display them on a dropdown .
What I want to do, is have a hidden field that would have the id of the value.
My JSON File returns something like this :
{ "name": "Emily"
"id" : 1
"jobData": [
{
"id":1
"loc":"AL"
},
{
"id":2
"loc":"BG"
}
]
Once I select Emily from my users, my dropdown gets filled with Locations of her job.
How do I also save the Id of the location in a hidden field so that I can send it to my controller?
This is my JS function:
function AutoCompleteS() {
$("#basics").keyup(function(e) {
this.query = e.target.value;
var options = {
url: function(query) {
return "/getUser/"+ query
},
getValue:"name"
list: {
onClickEvent: function() {
var value = $("#basics").getSelectedItemData();
function toArray(value){
return value.loc;
}
var allLocations=value.jobData.map(toArray);
$.each(allLocations,function(i,p){
$('#select').append($('<option></option>').val(p).html(p));
})
}
}
};
$('#basics').easyAutocomplete(options);
});
}
How do I get and pass the id ?
EDIT:
html code:
<label for="client1" class=" control-label">First Client</label> <input type="text" name="client" value="" class="form-control input-lg " id="basics"/>
<label for="sel1">Select location:</label>
<select class="form-control input-lg" id="select" >
<option></option>
<input type="text" class="hidden" />
</select>
easyAutocomplete issues:
Your code should be more like this (see remote data source example) - i.e. you should only call easyAutocomplete once:
$("#basics").easyAutocomplete({
url: function(query) {
return "/getUser/" + query;
},
getValue: "name",
list: {
// ...
}
});
HTML issues:
Move the input outside the select, and give them both names (so the values can be submitted to server):
<select class="form-control input-lg" id="select" name="location">
<option></option>
</select>
<input type="text" class="hidden" name="job-id" id="job-id">
To set the value of the hidden field when the select value changes, you need a change handler:
function updateSelect(jobData) {
// Reset options:
$("#select")
.empty()
.append(new Option());
// Add locations:
jobData.forEach(function(job) {
$("#select").append(new Option(job.loc));
});
// Handle dropdown change:
$("#select")
.off("change")
.on("change", function() {
// Reset job id (needed when user selects blank option at top of dropdown)
$("#job-id").val("");
var selectedLocation = this.value;
jobData.forEach(function(job) {
if (job.loc === selectedLocation) {
// Copy job id to hidden field:
$("#job-id").val(job.id);
}
});
});
}
Call updateSelect from your easyAutocomplete onClickEvent handler:
onClickEvent: function() {
var value = $("#basics").getSelectedItemData();
updateSelect(value.jobData);
}

How to `update` new value choosing from `select box` on click save button?

How to update new value choosing from select box on click save button.
I am using ng-click function like this in my JS function for update button:
$scope.updateDealDetail = function updateDealDetail (){
$scope.showEditView = !$scope.showEditView;
$scope.dealDetail.decisionMakerDetail.email = $scope.selectedid;
}
My function for edit button:
$scope.editUserDetail = function editUserDetail(){
$scope.showEditView = !$scope.showEditView;
$scope.showSubmitView = !$scope.showSubmitView;
deal.getIdData($scope.accountDetail. accountUsers[0].role,$scope.accountDetail.id).then(function successCb(data){
$scope.editIdOptionsData=data;
$scope.selectedid = $scope.editIdOptionsData[0].email;
});
};
and my HTML for bitton click is like this :
<select ng-model="selectedid" class="form-control">
<option ng-selected="selectedid" ng-repeat="eiod in editIdOptionsData" value="{{eiod.email}}">{{eiod.email}}
<button ng-click="updateDealDetail(eoid.email)" ng-disabled="dealDataSaveButtonDisabled">Update</button>
I am trying to this through ng-repeat because of by using ng-options my data through API is now showing in the box. But My data which is on first index is only getting set. What to do to set the a default value for the selection box and by selection any value, onclick need to update that value.
Don't use ngRepeat to render options, this is your problem. Correct code would be:
<select class="form-control"
ng-model="selectedid"
ng-options="eiod.email as eiod.email for eiod in editIdOptionsData">
</select>
Best practice to use ng-options, ng-model and ng-change on the <select> element
Online demo - https://plnkr.co/edit/Gaa8sMgerRv6chio4iYa?p=preview
html
<select
ng-model="selectedItem"
ng-change="onSelectedItemChanged()"
ng-options="item as item.email for item in items"></select>
js
app.controller('MainCtrl', function($scope) {
$scope.items = [{
email: 'asd1#asd.com'
}, {
email: 'asd2#asd.com'
}];
$scope.selectedItem = $scope.items[0];
$scope.onSelectedItemChanged = function() {
alert('you changed it to ' + $scope.selectedItem.email);
}
});

Populate dropdown list dynamically in AngularJS

I'm trying to generate dynamic form based on the key of document fields and using ng-if attribute in AngularJS.
Ex:
- If field name is "name|string" then populate textfield
- If field name is "name|select" then populate dropdownlist
- If field name is "name|datepicker" then populate datepicker
Following is the code:
<div class="form-group" ng-repeat="(index, formVal) in providerModelData" ng-if="!$first">
<label>{{mySplit(index,0) | uppercase}}</label>
<div ng-if="!mySplit(index,1)">
<input type="text" class="form-control" ng-model="providerModelData[index]">
</div>
<div ng-if="mySplit(index,1) == 'datepicker'">
<input type="text" class="form-control" ng-model="providerModelData[index]">
</div>
<div ng-if="mySplit(index,1) == 'select'">
<select class="form-control" ng-init="getDropdownData(index,colName)" ng-options="dropdown._id for dropdown in dropdownData[colName]">
<option value="">Select</option>
</select>
</div>
</div>
controller:
$scope.mySplit = function(string, nb) {
var array = string.split('|');
return array[nb];
}
textfields are working fine and populating data but I'm facing issue while populating dropdown fields.
Example: I've two dropdown fields in my mongodb document i.e. city|select and state|select
I'm trying to use ng-options to call function by passing index and colName (document name) to populate dropdownlist but its not working.
Following is the code:
$scope.dropdownData = {};
$scope.getDropdownData = function (query, colName) {
$http.get('/getdropdowndata/', {
params: {
query: query,
colName: colName
}
}).success(function (response) {
$scope.dropdownData[colName] = response;
});
};
Express:
router.route('/').get(function (req, res) {
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
console.log(query.query);
db.collection(query.colName).aggregate([{
"$group":{
"_id":"$"+query.query
}
}],function (err, docs) {
console.log(docs);
res.json(docs);
});
});
Initially I tried calling function in ng-repeat but it was going into infine loop. Then later I tried ng-init options but it only calls or initialize once which is not working in my case. Here I need to call function dynamically and based on that I want to populate dropdown for different fields.
Any help would be appreciated.
Your view is completely messed up as far I see it you are missing
ng-model
for your select input.
Your JSON is improper its missing , before {'id_':'Arizona'}
Try to get response in your controller and push it to array and make use of that array in your View :
$scope.getDropdownData=function(query, colName){
$http.get('/getdropdowndata/', {
params: {
query: query,
colName:colName
}
}).success(function (response) {
var returnArray = [];
alert(JSON.stringify(response));
angular.ForEach(response,function(option){
//parse response and push it to returnArray
returnArray.push(option);
});
return returnArray;
});
}
View :
<div class="form-group">
<select class="form-control" ng-model="selection" ng-options="dropdown._id for dropdown in getDropDownData()">
<option value="">Select</option>
</select>
</div>
Here is the link to Codepen
.
Consider the following solution:
In your controller, set up a variable for the dropdown data:
$scope.dropdownData = {};
Then change your getDropdownData function to:
$scope.getDropdownData=function(query, colName){
$http.get('/getdropdowndata/', {
params: {
query: query,
colName:colName
}
}).success(function (response) {
alert(JSON.stringify(response));
$scope.dropdownData[colName] = response; // This will put data into our html file
});
}
And the HTML for your dropdown case should be:
<div ng-if="mySplit(index,1) == 'select'">
<select class="form-control" ng-init="getDropdownData(index,colName)" ng-options="dropdown._id for dropdown in dropdownData[colName]">
<option value="">Select</option>
</select>
</div>
I used the notorious ngInit to make the call from getting data for the server. Perhaps there's a better way that I didn't consider. But in any case, the idea is to make the call to the server, and save the data in a way that you can fetch it easily from the view.
Edit
I don't know why, but for some reason this solution doesn't work with ng-options. It does, however, work when using it like this:
<select class="form-control" ng-init="getDropdownData(index,colName)">
<option value="">Select</option>
<option ng-repeat="dropdown in dropdownData[colName]" value="dropdown._id">{{dropdown._id}}</option>
</select>
See a simple example here.
Finally I solved it myself. Thanks #Rishab777 and #yarons for guiding me.
Here's the view code:
<div ng-if="mySplit(index, 1) == 'select'">
<select class="form-control">
<option value="">Select</option>
<option ng-model="providerModelData[index]" ng-selected="providerModelData[index]" ng-repeat="dropdown in dropdownData[index]" value="{{dropdown._id}}">{{dropdown._id}}</option>
</select>
</div>
and controller:
$scope.showModal = false;
$scope.toggleModal = function (colId, colName) {
$http.get('/collectiondata/' + colId + '/collectionName/' + colName).success(function (response) {
$scope.colName = colName;
$scope.colId = colId;
for (var key in response) {
if (response.hasOwnProperty(key)) {
if ($scope.mySplit(key, 1) === 'select') {
$scope.getDropdownData(key, colName);
}
}
}
$scope.providerModelData = response;
$scope.showModal = !$scope.showModal;
});
};
$scope.dropdownData = {};
$scope.getDropdownData = function (query, colName) {
$http.get('/getdropdowndata/', {
params: {
query: query,
colName: colName
}
}).success(function (response) {
$scope.dropdownData[query] = response;
});
};
Now the issue is ng-selected="providerModelData[index]" is not working and its showing last item as selected only.

Trigger "console.log" with message "onfocusleave" in select element directive with AngularJS

I build this directives for AngularJS+Symfony2 project:
app.directive('country', ['$http', function($http) {
return {
restrict: "C",
link: function(scope, element, attrs) {
$http.get(Routing.generate('countries')).success(function(data) {
if (data.message) {
scope.message = data.message;
} else {
scope.countries = data.entities;
}
}).error(function(data, status, headers, config) {
if (status == '500') {
scope.message = "There is not connection with server";
}
});
}
};
}]);
app.directive('state', ['$http', '$parse', function($http, $parse) {
return {
restrict: "C",
link: function(scope, element, attrs) {
scope.$watch(attrs.trigger, function() {
state = $parse(attrs.trigger)(scope);
iso = state != undefined && state.iso_country != undefined ? state.iso_country : state;
if (iso !== undefined && iso !=='') {
$http.get(Routing.generate('states') + '/' + iso).success(function(data) {
if (data.message) {
scope.message = data.message;
} else {
scope.states = data.entities;
}
}).error(function(data, status, headers, config) {
if (status == '500') {
scope.message = "There is not connection with server";
}
});
}
});
}
};
}]);
And this is how I use in my template file:
<select class="country"
ng-model = "country.standard_address"
ng-options = "country.name for country in countries">
<option value="-1">{{ "Select country" | trans }}</option>
</select>
<select class="state"
ng-model = "state.standard_address"
ng-disabled = "!states"
ng-options = "state.name for state in states"
trigger = "country.standard_address">
<option value="-1">{{ "Select state" | trans }}</option>
</select>
I need to add some way to validate this fields in case user didn't change it and remain with value equal -1. I could do this on click event for submit button but I not enabled the button until the form has no errors. This is the code to handle this part:
<input type="button" class="button {% verbatim %}{{ step1Form.$valid && 'active' || 'gray'}}{% endverbatim %}" value="Continuar" ng-disabled="!step1Form.$valid" ng-click="nextStep(2)" />
how I can do this?
Quoting the docs on select (with ngOptions):
Optionally, a single hard-coded element, with the value set to an empty string, can be nested into the element. This element will then represent the null or "not selected" option.
You need to set the value of the hard-coded option to an empty string and add the required attribute to the select elements. This way, the step1Form will not be valid unless an option (other than the null option) is selected.
UPDATE:
Seems like I misunderstood yur requirements. In order to be able to display a message on blur, you can use ng-focus and ng-blur to set the value of a variable. Then have an element that is shown/hidden based on the value of that variable (also taking into account the validity of the select).
The code for the "country" select could look like this:
<select name="countrySelect" ng-model="country.standard_address"
ng-options = "country.name for country in countries"
ng-focus="countryFocused=true" ng-blur="countryFocused=false"
required>
<option value="">Select country</option>
</select>
<div ng-hide="countryFocused || step1Form.countrySelect.$valid">
ERROR !!! Select a country ASAP !
</div>
See, also, this (updated) short demo.

Categories