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.
Related
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/
I have the following project flow structure:
import_product.html
<div class="row custom_row">
<div class="col-md-2">Additional Duty: </div>
<div class="col-md-2">
<select class="form-control" [(ngModel)]="product.additional_duty_not_no" (change)="changeAddDutyNotSrNo()" required="required">
<option value=" ">-- SELECT --</option>
<option *ngFor="let add_duty_not_no_data of product.addl_duty_not_nos" value="{{ addl_duty_not_no_data.notification_no }}">{{ addl_duty_not_no_data.notification_no }}</option>
</select>
</div>
import_product_component.ts
getAddlNotificationDuty() {
var url = 'api/getBasicNotificationDuty';
var add_duty_not_no_data : any;
var ref = this;
this.jobService.loadRemoteUrl(url)
.subscribe(
data => { add_duty_not_no_data = data},
err => console.error(err),
() => {
if (add_duty_not_no_data.length > 0) {
ref.product.addl_duty_not_nos = add_duty_not_no_data;
}
}
);
}
Now the call is made to the API backend powered by Laravel PHP which successfully returns the desired data in the following array format:
[{"notification_no":"012/39"},{"notification_no":"007/97"},{"notification_no":"999/85"}]
But unfortunately the dropdown in the frontend is not getting populated with the concerned values. There are no errors in the console.
console.log till the .ts component shows objects being returned successfully but it is not getting appended to the dropdown.
Please let me know if you want any more details. Any help will be highly appreciated.
where do you get
basic_duty_not_no_data
from?
also I recommend using slightly different flow with handling ajax call
add_duty_not_no_data: any
getAddlNotificationDuty() {
var url = 'api/getBasicNotificationDuty';
this.jobService.loadRemoteUrl(url)
.subscribe(
data => {
if (data.length > 0) {
this.add_duty_not_no_data = data;
}
},
err => console.error(err)
);
}
i am getting a data from json file and the values using in dropdown but i dont want to use all values,I want to select only three values in my dropdown.
You can filter the list at the time of feeding it to the dropdown.
<select ng-model="toType" class="form-control" required ng-change="ConvertCurrency()"
ng-options="k for (k, v) in (rates | 'yourfilter') track by v"></select>
[UPDATE]
I tried to access the API, and found out that res.data.rates is an object and not an array.
So if you only have to show these 3 values, the easy approach would be to create a new array in controller:
var ratesToDisplay = [];
ratesToDisplay.push({rate:'USD', value: res.data.rates.USD});
ratesToDisplay.push({rate:'EUR', value: res.data.rates.EUR});
ratesToDisplay.push({rate:'CAD', value: res.data.rates.CAD});
and feed this new filtered array to your dropdown.
<select ng-model="selectedRate" ng-options="rate.value as rate.rate for rate in ratesToDisplay">
<option value="" disabled>Please Select</option>
</select>
I hope this helps.
For 2nd part of your problem
You can implement the ng-change() method and call the API from that method. Ex:
function onDDChange(){
$http.get('http://api.fixer.io/latest?' + $scope.fromType.label)
.then(function(res) { \\logic for success call back
\\ call convert currency method from here.
});
}
HTML:
<select ng-model="fromType" class="form-control" required
ng-change="onDDChange()" ng-options="f as f.label for f in rates">
I have written this code and it is working for me
angular.module('CurrencyConv', [' ']).controller('ConvertCtrl', ['$scope', '$http', function($scope, $http) {
$scope.rates = [];
$scope.toType = {};
$scope.fromType = {};
$http.get('http://api.fixer.io/latest?base').then(function(res) {
$scope.fromValue = 1;
$scope.ConvertCurrency();
var i = 0;
angular.forEach(res.data.rates, function(value, key) {
if (key == "USD" || key == "EUR" || key == "CAD") {
$scope.rates.push({ value: value, label: key });
// $scope.toType = $scope.rates.CAD;
// $scope.fromType = $scope.rates.USD;
}
i++;
});
});
<select ng-model="fromType" class="form-control" required ng-change="ConvertCurrency()" ng-options="f as f.label for f in rates">
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
Hello thanks for help me. I have two select field, one select field for states, and other select for the cities. I am trying to load cities dinamically from the JSON generated in the server, when the user change the selected state.If you can help, many thanks..
JavaScript:
var geo = function(app){
app.controller("geoCtrl",function($scope, $http, geoFactory){
$scope.mcpios = [];
$scope.dptos = [];
$scope.$watch('dpto', function (nuevoValor, viejoValor) {
if(!viejoValor || !nuevoValor) return;
if (nuevoValor.id_departamento === viejoValor.id_departamento) { return; }
geoFactory.actMucpios($scope.dpto.id_departamento).success(function(rs){
console.log(rs[0]);
$scope.mcpios = rs[0];
});
}, true);
geoFactory.get().success( function(rs){
$scope.dptos = rs[1];
$scope.dpto = $scope.dptos[0];
});
});
app.factory("geoFactory", function($http){
var factory = {};
factory.get = function(){
return $http.get("aplicacion/controladores/controlador_geo.php?listar");
};
factory.actMucpios = function(id_dpto){
return $http.get("aplicacion/controladores/controlador_geo.php?listar&id_dpto=" + id_dpto);
}
return factory;
});
}
HTML:
<select ng-controller="geoCtrl" ng-change="actulizar()" ng-model="dpto" class="col-md-12" ng-options="dpto.nombre for dpto in dptos" >
<option ng-repeat-start>Seleccione un Departamento</option>
<option value="{{dpto.id_departamento}}" ng-repeat="dpto in dptos">{{dpto.nombre}}</option>
</select>
<select ng-model="mcpio" class="col-md-12" ng-controller="geoCtrl">
<option ng-repeat-start>Seleccione una Ciudad</option>
<option value="{{mcpio.id}}" ng-repeat="mcpio in mcpios | filter:dpto.id">{{mcpio.nombre}}</option>
</select>
I hope that you can help me... Thanks
I create the plunkr below that simulates making a call to a service to retrieve a list of states. Then when a state is selected it will retrieve from the object (or if you need you could request the list of states in the $scope.watch statement to retrieve the cities then set the list of cities to scope collection for the cities and each time you select a new state the list of cities will change.
Here's a link to see the working example : http://plnkr.co/edit/ntUblVSSoBzp053GuYvv?p=preview