ajaxform select2 concatenate multiple IDs - concatenation

I have a select2 search form with an ajaxform that concatenates new form entries into the original select2 search form. If more than one new entry is added, the new text values concatenate correctly into the search field, however, any new hidden ID replaces the existing one. It appears to be added because all new text values shows in the select2 search field. I think the issue is that the new ID should be concatenating to the hidden cropstageid field in addition to the text field concatenating to the search field. I'm not sure how to do this. Your help is appreciated.
<script>
$(document).ready(function() {
$("#search").select2({
width: '60%',
allowClear: true,
minimumInputLength: 0
});
$('#btnSubmit').on('click', function() {
$.ajax({
asynch : true,
type : 'POST',
dataType : 'json',
url: '../cfc/stages.cfc?method=addstage&returnformat=json',
//all form fields submitted to url
data: $("form").serialize(),
success : function(data, textStatus) {
//close the modal
$('#stagemodal').modal('hide');
//set the returned data to a variable
var fullname = $('#stagename').val();
$("#cropstageid").val(data.DATA);
//get current selection
var selection = $(search).select2("data");
//add a new item to the selection
selection.push({id: data.DATA, text: fullname})
//set the updated selection
$(search).select2("data",selection);
//reset form
$('#addstageform')[0].reset();
//output data to console
console.log(data.DATA);
}
});
});
});
</script>
<cfform name="stageform" id="stageform" action="settings_form_action.cfm" method="post" ENCTYPE="multipart/form-data">
<h4 class="text-primary">Select Crop Stages</h4>
<input type="hidden" id="cropstageid" name="cropstageid">
<cfselect id="search" multiple name="cropstageid" >
<cfloop query="stages" >
<option value="#cropstageid#" >#stage#</option>
</cfloop>
</cfform>
*AjaxForm for new entries
<cfform id="addstageform" name="addstageform" action="" method="post">
<input type="text" name="stagename" id="stagename" autofocus size="35">
<input type="button" id="btnSubmit" value="Add" /><
</cfform>

Thanks to the help of a colleague, the solution is below:
in success we are no longer attaching to a hidden field, so remove
$("#cropstageid").val(data.DATA);
in success, add  
$('#search').append('' + fullname + '');
this line adds another select option from the newly added ajaxform record
no longer need hidden value since it is attaching as the select option, so delete hidden cropstageid form field inside the form.
The cleaned up script is below:
<script>
$(document).ready(function() {
$("#search").select2({
width: '60%',
allowClear: true,
minimumInputLength: 0
});
$('#btnSubmit').on('click', function() {
$.ajax({
asynch : true,
type : 'POST',
dataType : 'json',
url: '../cfc/stages.cfc?method=addstage&returnformat=json',
//all form fields submitted to url
data: $("form").serialize(),
success : function(data, textStatus) {
//close the modal
$('#stagemodal').modal('hide');
//set the returned data to a variable
var fullname = $('#stagename').val();
//get current selection
var selection = $('#search').select2("data");
//add the new option to the select
$('#search').append('<option value="' + data.DATA + '">' + fullname + '</option>');
//add a new item to the selection array
selection.push({
id: data.DATA,
text: fullname
});
//set the updated selection
$('#search').select2("data",selection);
//reset the modal form
$('#addstageform')[0].reset();
//output to the console
console.log(data.DATA);
}
});
});
});
</script>

Related

How to I use http.post in angular js to retrieve the rows of my datatable that are checked?

Hi I have a datatable with id, name, etc. and have checkboxes added within the angular js
e.g.
vm.dtColumns = [
DTColumnBuilder.newColumn(null).withTitle(titleHtml).notSortable()
.renderWith(function(data, type, full, meta) {
vm.selected[full.ID] = false;
return '<input type="checkbox" class="checkedtestids" ng-model="showCase.selected[' + data.ID + ']" ng-click="showCase.toggleOne(showCase.selected)">';
}),
I have checkboxes that can select all rows from the header or individually.
I have also got a var that keeps the id and changes the boolean state from true to false depending on the checkbox being checked or not.
var vm = this;
vm.message = '';
vm.someClickHandler = someClickHandler;
vm.selected = {};
vm.selectAll = false;
vm.toggleAll = toggleAll;
vm.toggleOne = toggleOne;
My html code to display this vm.selected = {}; is as follows:
<div ng-controller="WithAjaxCtrl as showCase">
<blockquote>Please click on a row</blockquote>
<p class="text-danger">
You clicked on: <strong>{{ showCase.message }}</strong>
</p>
<table datatable="" dt-options="showCase.dtOptions"
dt-columns="showCase.dtColumns" class="row-border hover"></table>
<p class="text-danger">You selected the following rows:</p>
<p>**<pre ng-model="showCase.selected">{{ showCase.selected |json }}</pre**>
If I click on these ids :
enter image description here
Then the following is reflected below:
enter image description here
{
"2457937718692": true,
"2457985718634": false,
"2454757950532": true,
How do I send this array vm.selected that indicates checked or not to my java spring controller which will then use them for another purpose?
I have tried to use $http.post() and $http.get() without success.
You don't need to pass the ID in the ng-model to identify the selected checkboxes because the array of object is bound to the view, instead you can pass the boolean variable and use filter directive https://docs.angularjs.org/guide/filter.
Eg.:
JAVASCRIPT
vm.data = ['a','b','c'];
var selected = [];
var vm.filterSelectedData = function(){
selected = $filter('filter')(data, {checked: true});
}
HTML
<div ng-repeat="element in showCase.data">
<input type="checkbox" class="checkedtestids" ng-model="element.selected" ng-change="showCase.filterSelectedData()" />
</div>
to send the selected items to the server you just need to create a json object with the array of those selected items.
http.post('url', {selectedItems:selected})
.success(function(){ // calback function })
.error(function(){ // error function })
see plunker
https://plnkr.co/edit/iJf7onwLUKckQDzBP2pT

Get value from a database and set it as selected value of a dropdownlist using Angularjs

I get some values from a database. With one of the values I get, I would like to have that as a selected value in the dropdownlist when another dropdownlist changes. Please see code below:
index
<div class="form-group">
<select ng-model="editProject.ClientId" name="client_id" ng-options="item as item.Company for item in clientList" class="form-control">
</select>
<div>-->{{editProject.ClientId}}</div> <=== This is to see if I am getting the value from js
<span style="color: red;" ng-show="formEditProject.client_id.$touched && formEditProject.client_id.$invalid">Select a client</span>
</div>
js
//=== This is the client list in the dropdown list ===>
$scope.editClient = {
"ClientId": null,
"Company": null,
"ContactPerson": null,
"EmailAddress": null
}
//== Retrieves clients from the database on page load ===>
$scope.getClients = function () {
return $http.get('/Clients/GetClients')
.then(function (response) {
$scope.clientList = response.data;
});
};
//== Event when a different dropdownlist is changed ===>
$scope.onProjectEditChange = function () {
console.log($scope.selectedProjectId.Id);
$http({
url: '/Project/GetProjectByProjectId',
params: {
"id": $scope.selectedProjectId.Id
},
method: 'post'
})
.then(function (response) {
$scope.editProject.Id = response.data.Id;
$scope.editProject.Description = response.data.Description;
$scope.editProject.ClientId = response.data.ClientId;
$scope.editProject.ProjectLead = response.data.ProjectLead;
$scope.editProject.IsApproved = response.data.IsApproved;
});
}
I am able to see the clientId change in the <div>-->{{editProject.ClientId}}</div> but it doesn't change the selected value of the dropdownlist.
Use ng-change option and check it
<div class="form-group">
<select ng-model="editProject.ClientId" name="client_id" ng-options="item as item.Company for item in clientList" class="form-control" ng-change='changeSelectedItem(editProject.ClientId")'>
</select>
<div>-->{{editProject.ClientId}}</div> <=== This is to see if I am getting the value from js
<span style="color: red;" ng-show="formEditProject.client_id.$touched && formEditProject.client_id.$invalid">Select a client</span>
</div>
$scope.changeSelectedItem = function(client){
$scope.editProject.ClientId= client.ClientId;
}

AngularJS form input with Google Places API not saving full string

I am trying to capture data from a form input that utilizes the Google Places API.
If I begin typing a location like for instance "Kingst", and I then choose "Kingston ON, Canada" from the drop-down list of related suggestions, the input field populates with "Kingston ON, Canada" as it should.
However, when I hit the save button, only what I originally typed is saved to the database. ie: "Kingst".
Here is a possible hint:
During multiple tests, I have found out that if I put my cursor back into that same input field and then remove it again, the proper full string is saved to the database when I hit the submit button.
I'm not sure how to get the full string to save upon selecting a suggestion from the dropdown, without having to put my cursor into the field and change the string.
In my form I have this input field:
<form>
<div class="form-group">
<input id="eventLocation" placeholder="Event Location..." class="form-control" name="eventLocation" ng-model="newEvent.location">
</div>
<div class="form-group">
<input type="hidden" id="eventLat" placeholder="Latitude..." class="form-control" name="eventLat" ng-model="newEvent.lat">
</div>
<div class="form-group">
<input type="hidden" id="eventLng" placeholder="Longitude..." class="form-control" name="eventLng" ng-model="newEvent.lng">
<button type="submit" ng-disabled="fuck.$invalid" class="btn btn-primary pull-right" ng-click="addEvent(newEvent);newEvent = null;">send</button>
</form>
In the HTML below the form I have the following:
<script>
// This example displays an address form, using the autocomplete feature
// of the Google Places API to help users fill in the information.
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
var placeSearch, autocomplete;
function initAutocomplete() {
// Create the autocomplete object, restricting the search to geographical
// location types.
autocomplete = new google.maps.places.Autocomplete(
/** #type {!HTMLInputElement} */(document.getElementById('eventLocation')),
{types: ['geocode']});
autocomplete.addListener('place_changed', fillInLatLng);
}
function fillInLatLng() {
var place = autocomplete.getPlace();
var lat = place.geometry.location.lat(),
lng = place.geometry.location.lng();
var eventLat = document.getElementById('eventLat');
var eventLon = document.getElementById('eventLng');
eventLat.value = lat;
eventLon.value = lng;
console.log(lat);
console.log(lng);
}
// Bias the autocomplete object to the user's geographical location,
// as supplied by the browser's 'navigator.geolocation' object.
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
var circle = new google.maps.Circle({
center: geolocation,
radius: position.coords.accuracy
});
autocomplete.setBounds(circle.getBounds());
});
}
}
</script>
In the controller I have:
$scope.addEvent = function(newEvent) {
var eventLat = document.getElementById('eventLat').value;
var eventLng = document.getElementById('eventLng').value;
if (newEvent) {
// push a event to the end of the array
$scope.events.$add({
location: newEvent.location,
latitude: eventLat,
longitude: eventLng,
createdBy: user.uid,
createdAt: Firebase.ServerValue.TIMESTAMP
})
// display any errors
.catch(alert);
}
document.getElementById('eventLat').value = '';
document.getElementById('eventLng').value = '';
};
I solved this issue by doing the following:
In my controller I added:
var eventLoc = document.getElementById('eventLocation').value;
...
$scope.events.$add({
location: eventLoc,
...
Better you used this code. Because while using this code circular to json conversion is build inside the js
Controller.js file
.directive('googleplace', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, model) {
var options = {
types: [],
componentRestrictions: {country: 'in'}
};
scope.gPlace = new google.maps.places.Autocomplete(element[0], options);
google.maps.event.addListener(scope.gPlace, 'place_changed', function() {
scope.$apply(function() {
model.$setViewValue(element.val());
});
});
}
};
});
Note:If u can read on specfic country means , include this tag
componentRestrictions: {country: 'in'}
In HTML file you just add googleplace tag only.

How to manually change the $error values for input tags - Angularjs

I am submitting a form via the angular $http and I want to give an error if the user bypassed the angularjs validation. I want to use the same error tag as if they didn't bypass the validation, userForm.name.$invalid && !userForm.name.$pristine how can I manually set this value ?
HTML
<body>
<form ng-controller="UserController" ng-model="userForm" name="userForm" ng-submit="createUser()">
<legend>Create User</legend>
<label>Name</label>
<input type="text" id="name" name="name" ng-model="user.name" placeholder="User Name" required>
<!-- HERE IS WHERE THE ERROR SHOWS -->
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine"
<button class="btn btn-primary">Register</button>
</form>
</body>
ANGULAR JS
$http({
method : 'POST',
url : '/create',
data : user,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
}
})
.success(function(data) {
// I want to do something like this
name.$invalid = true;
name.$pristine = false;
});
I want to do something like what is in the success function. Therefore it will show the error message.
If you have access to scope in http success callback, you can do this to set the validity or mark it as dirty.
scope.userForm.name.$setDirty();
OR
scope.userForm.name.$setValidity('serverError', false); // creating a new field in $error and makes form field invalid.
To set the validity or pristine values of the form, you must use the function provided by the form.FormController. You can set the form to pristine or dirty but you cannot set a form directly to valid to not. You must set a particular model to invalid which will trigger the form value to invalid which will trigger the form to be invalid (https://docs.angularjs.org/api/ng/type/form.FormController).
//UserController
//$scope.userName is your object which has it's own controller using Angular Forms.
app.controller("UserController", function($scope){
$http({
method : 'POST',
url : '/create',
data : user,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
}
})
.success(function(data) {
// I want to do something like this
$scope.userForm.$setDirty(); //Sets $pristine to false; Alternatively, you could call $setPristine() to set $pristine to true
$scope.userForm.name.$setValidity("length",false); //In your case, the "length" validation is likely something different or will be generic. This enables you to have name fail validation based multiple rules (perhaps length and unique)
});
});
If you want to check a specific field for validity, you can use a custom directive:
app.directive('customValidation', function(dataService) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue){
//first, assume the value is valid, until proven otherwise
ctrl.$setValidity('customValidation', true);
//check against the API
if(viewValue.length > 0 && !ctrl.$error.customValidation) {
dataService.checkValidity(viewValue).then(function(response){
//API logic here
var results = response.data;
if(results.isNotValid)
ctrl.$setValidity('customValidation', false);
}).catch(function(response){
//some error occurred
ctrl.$setValidity('customValidation', false);
});
}
});
}
};
});
To use it:
<input custom-validation ng-model-options="{updateOn: 'default blur', debounce: { 'default': 700, 'blur': 0 }}" />

Typehead displays wrong on certain input

I am using a uiTypehead for input selection.
It works well except for a simple fact. My inputs always have the form like
{name: "Las Vegas McCarran International (LAS)<span
class="country">United States</span>", iata: "LAS"}
So I insert <span class="country">...</span> from my backend into the string.
When I then type in "veg" into the input field, that's all fine.
However, when typing in "las" instead, following happens:
What basically happens is, that my system assumes "class" to be part of my desired string does the following in the view:
<span c<strong="">lass="country">United States</span>
Basically, it recognizes "las" as the string and puts a strong into that part so that it is not displayed correctly.
My view, service and my controller look as follows:
Service:
angular.module('tripdeltaApp').service('airportService',['$http',function($http){
this.airport = function (entry) {
return $http({
method: 'POST',
url: '/airport',
data: {'search': entry}
}).then(function (response) {
return response.data.map(function (item) {
//console.log(item);
return item;
});
});
};
}]);
Controller:
$scope.onSelect = function ($item, $model, $label,to,index) {
$model = urlParser.cleanAirport($model);
if(to && $scope.flightArray[index+1] && !$scope.flightArray[index+1].from) {
$scope.flightArray[index+1].from = $model;
}
};
and view:
<input type="text"
ng-focus="inputFocus=false"
ng-blur="inputFocus=true"
ng-model="flight.to"
placeholder="{{'TO'|translate}}"
name="arrivalAirport"
typeahead="data as data.name for data in getAirport($viewValue)"
class="form-control"
typeahead-editable="false"
typeahead-on-select="onSelect($item, $model, $label,1,$index)"
autocomplete="off"
select-on-click
required>
Any idea how to solve that?
I think your best bet is to use a Custom Template, as described in the Typeahead example with the flags, instead of putting markup into your data.
You'd change your data to be like this:
{name: "Las Vegas McCarran International (LAS)", country: "United States", iata: "LAS"}
and use a template something like this:
<script type="text/ng-template" id="customTemplate.html">
<div>
{{match.model.name}}
<span class="country">{{match.model.country}}</span>
</div>
</script>
Update
If you can't change the data on the backend, you could preprocess your data as it gets loaded into JavaScript:
var re = new RegExp('^([^<]+)<span class="country">([^<]+)<\/span>');
angular.module('tripdeltaApp').service('airportService',['$http',function($http){
this.airport = function (entry) {
return $http({
method: 'POST',
url: '/airport',
data: {'search': entry}
}).then(function (response) {
return response.data.map(function (item) {
//console.log(item);
var matches = item.name.match(re);
item.name = matches[1];
item.country = matches[2];
return item;
});
});
};
}]);
The regular expression may need some tweaking, based on the specific data you have. If any airport "name" fields have a "<", that would obviously cause trouble. You may also need to mess with spacing, location of quotes, etc.

Resources