Static Dropdown to Dynamic Dropdown Coldfusion - html

I am new here at stack overflow.
I need to create a static dropdown and then create a dynamic drop down based on the values that was chosen in the static dropdown. Just coldfusion and html. NO other fancy stuff.
So from the first drop down the user would chose: color, id, officer, school and hit "continue" button
Then on the same page or different, if color is chosen it will do a query on database and give out the results for the different colors, if id is seclected it will give a list of id numbers from a query. Same thing for officer or school, if those variables are chosen.
I can do the dropdown box, and get the queries but I am stuck in getting the results from the frist dropdown box to the queries. Below is my code:
<cfform method="POST" action="">
<select name="dropDownOne" required="yes" onchange="this.form.submit()">
<option>Select Report Type</option>
<option value="color">Color</option>
<option value="id">ID</option>
<option value="officier">officier</option>
<option value="school">school</option>
</select>
<input type="Submit" name="Continue" value="Continue">
<cfif isDefined('form.selectType')><cfif form.dropDownOne eq "color">
<option>Select Color</option>
<cfloop query="colorlist">
<option value="#color_id#"
<cfif isDefined('form.selectcenter')>
<cfif form.selectcenter eq "#color_id#">selected</cfif></cfif>>#color#</option>
</cfloop>

Unless you resubmit the page after each selection and requery for the dependent dropdown values, you have to use some kind of client side js and/or ajax.
I think that is what you are sort of trying to show you are doing? It is not too clear what you are trying to do; do you want the dependent dropdown to reflect what you choose and automagically change?
So you would need to have big if wraps around all the possible drop downs depending on what they picked and submitted? And why would the user only be able to choose one of these things at a time? This seems like a very cumbersome way to code it up, and a cumbersome interface.
This will show you how to wire up using cfselect, but I think it is still a bit strange how you want to do this. Are you going to save off each piece and show that or use that somewhere? Or is this just a proof of concept?
And I would probably display all the stuff all the time. A dependent drop down makes more sense for things like Car selectors (Year, Make, Model, Trim level) where each is uniquely dependent on the previous value. I am not sure what you are trying to hook together from the question you asked.
Anyway, ColdFusion does have a <cfselect> which will wire that up for you automagically, though personally I would just use jQuery/Ajax.
Here is how you might do this using the tag:
1) Don't submit your form onChange.
2) Use cfselect to wire the dropdowns together.
3) You need to have methods to call queries that are remote accessible for the binding to work.
<cfif isDefined('Form.DropDownOne')>
<!--- Do some action here --->
<cfdump var="#form#">
</cfif>
<cfform>
<label>Select A Report</label>
<cfselect name="dropDownOne" id="dropDownOne" required="yes"
<!--- The display attribute will map the "name" column to the option display text area --->
<!--- The value attribute will map "value" column to the option value (what is submitted)--->
display='name ' value='value'
<!--- The cfc should send back a query with name and value columns. --->
<!--- The dot path should point to the location of the cfc. --->
bind="cfc:com.app.code.myDropDowns.getCategories()" bindonload="true">
<option>Select Report Type</option>
</cfselect>
<label>Select A Value</label>
<cfselect name="dropDownTwo" id="dropDownTwo" required="yes"
display='name' value='value'
<!--- This method takes the value from the other drop down. --->
<!--- CF uses {} to denote the binding of the element to pass through. --->
<!--- This binding will occur automatically on any change to the dropDownOne element (including load). --->
bind="cfc:com.app.code.myDropDowns.getDetails({dropDownOne})" >
<option>Stuff</option>
</cfselect>
<input type="Submit" name="Continue" value="Continue">
</cfform>
Here I made a myDropDowns.cfc that will return a hand-built query (I do not know how/where you are storing data, so swap out with real query as you like, just return a query to the request:
component output="false" persistent="false" displayname="myDropDowns" {
structAppend(variables, Application.Seq.Objects.oCore.injectCoreMethods() );
remote function getCategories() {
var q = queryNew('');
queryAddColumn(q,'name',['Select Report Type','Color','ID', 'Officer', 'School']);
queryAddColumn(q,'value',['Select Report Type','Colors','IDs', 'Officers', 'Schools']);
return q;
}
remote function getDetails(required string Category) {
var q = queryNew('');
if(Arguments.Category == 'Colors' ) {
queryAddColumn(q,'name',['Select Value','Red','Green','Blue', 'Yellow', 'Purple']);
queryAddColumn(q,'value',['','Red','Green','Blue', 'Yellow', 'Purple']);
} else if(Arguments.Category == 'IDs' ) {
queryAddColumn(q,'name',['Select Value','123','456','789', '1011', '978']);
queryAddColumn(q,'value',['','123','456','789', '1011', '978']);
} else if(Arguments.Category == 'Officers' ) {
queryAddColumn(q,'name',['Select Value','Johnson','Fredricks','Oppenheimer', 'Davis', 'Smith']);
queryAddColumn(q,'value',['','Johnson','Fredricks','Oppenheimer', 'Davis', 'Smith']);
} else if(Arguments.Category == 'Schools' ) {
queryAddColumn(q,'name',['Select Value','Central','Northridge','Fairview', 'Daring', 'South']);
queryAddColumn(q,'value',['','CJH','NRJH','FHS', 'DHS', 'SHS']);
} else {
queryAddColumn(q,'name',['Select A Report Type First']);
queryAddColumn(q,'value',['Yeah, do that']);
}
return q;
}
}
Here are a couple of queries wrapped in cat/list methods you could modify to point at your tables that should return the same style query as the hand coded ones. Substitute your database.tablename and column names, of course.
remote function getCats() {
var q = queryNew(''); // Create empty query, not really nec. Just to initiate as query type.
var oQ = new Query(); // Create query object to execute query against your DB
try { // I like to use try-catches, make it easier to figure out what is going on sometimes....
/* You don't have to set the datasource if you set it in the Application for CF9+*/
oQ.setDataSource('myDataSource');
// Query name is only really needed if caching or requerying as it becomes part of your cache signature
oQ.setName('qMyQueryCategories');
oQ.setCachedWithin(1); // 1 == 1 day/24 hours, .5 = 12 hours, etc)
oQ.setSQL("
SELECT
T1.Id,
T1.DisplayName AS Name,
T1.Category AS Value
FROM yourDB.yourCatTableHere T1
");
q = oQ.Execute().getResult();
return q;
} catch (any err) {
/*
* Returning the error will allow you to debug in the case you have a bad query.
* You can see the result in your F12 debug network tool.
* You could optionally call an error handler to log/email the error
* but then return the empty query to the UI request so it sort of keeps functioning...
* */
return err;
}
}
remote function getList(required string Category) {
var q = queryNew('');
var oQ = new Query();
try {
oQ.setName('qMyQuery#Arguments.Category#');
oQ.setCachedWithin(.04); // Approximately 1 hour (1/24=.0417)
oQ.setSQL("
SELECT
T1.Id,
T1.Category AS Cat,
T1.DisplayName AS Name,
T1.ValueKey AS Value
FROM [yourDB.yourDetailTableNameHere] T1
WHERE T1.Category = ? ;
");
// Parameterize your sql variable. CF will take care of quoting it properly, etc.
oQ.AddParam(value=Arguments.Category, cfsqltype='CF_SQL_VARCHAR' );
q = oQ.Execute().getResult();
return q;
} catch (any err) {
return err;
}
}
Just make sure you match the method names you call in your bindings to the ones you use for each method.

Related

Selected Options doesnt display on the field but is sent correctly to backend

So i have a project in which i have to display some data from the table. Now i want to change the size of the data based on a field above the table that is actually a select input field and sends a value to the angular controller. Now this is working perfectly except for the fact that the field doesn't show the selected number of data being displayed on the field.
This is the empty field. but the data is inserted correctly. Also on debugging I found another option here on the field that is not in the html code. Here's my code for the html and the controller.
View:
<li class="manual-dropdown pull-right">
<select id="ddPageSize" ng-model="PaginationInfo.pageSizeSelected" ng-change="ChangePageSize()" aria-controls="DepartmentTable" class="form-control pull-right">
<option value="5">5</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="-1">All</option>
</select>
</li>
Controller:
$scope.PaginationInfo = {
maxSize: 5, // Limit number for pagination display number.
totalCount: 0, // Total number of items in all pages. initialize as a zero
pageIndex: 1, // Current page number. First page is 1.
pageSizeSelected: 5, // Maximum number of items per page.
}
GetData(searched);
function GetData(searched) {
//debugger
//var noOfPages = 1;
var SearchData = $scope.StatusSearch.Search;
if (SearchData == "") {
searched = false;
}
var Displaysize = $scope.PaginationInfo.pageSizeSelected;
var index = $scope.PaginationInfo.pageIndex;
if (searched == false) {
Get("/User/GetData?Size=" + Displaysize + "&index=" + index, false).then(function (d) {
//$("#").val()
//$scope.userAccount.CountryID = $("#ddCountryOptions").val();
// $scope.PaginationInfo.maxSize = d.info.maxSize;
$scope.PaginationInfo.totalCount = d.totalSize;
$scope.PaginationInfo.pageIndex = d.index;
$scope.PaginationInfo.pageSizeSelected = d.size;
//$scope.noOfPages = $scope.PaginationInfo.totalCount / $scope.PaginationInfo.pageSizeSelected;
$scope.accountlist = d.GetList;
$scope.$apply();
})
}
else {
// alert($scope.SearchData.Search);
Get("/User/SearchData?inputstring="+ SearchData, false).then(function (d) {
$scope.accountlist = d.GetList;
$scope.PaginationInfo.pageIndex = index;
$scope.PaginationInfo.pageSizeSelected = Displaysize;
$scope.PaginationInfo.totalCount = d.totalSize;
$scope.$apply();
});
}
}
explanation for the Controller: The data is loaded on page load so the GetData() function is called immediately. the default page size is set to 5 as shown and when i make a change to the field i recall the GetData() function with page size as a argument and the back end does the rest and returns a amount of data that i asked for. Also the reason there are 2 ajax calls in this function is to implement a search function. which check if the input field is empty or has a value and based on that output the data.
What i want to know is why is the page size field on my dropdown empty when i select a value.
Edit:
After a bit more research i found that the ng-Model is making a empty option with the value of the option i selected. Now the problem still remains i don't know how to display the value in the empty object. if i do select another option as selected, my ng-model value does not change. So i am still stuck with this. Also i have already give the ng-model an default value of 5 the same as my first dropdown option. so in case i tag any other option as selected, the ng-model option will remain 5 no matter how many times i change the dropdown value.
Alright i kind of solved my issue, though I am not sure if this is a good way to do it.
So what i did is simply bind the pageSizeSelected Value to the html select element by id.
$("#ddPageSize").val(d.size)
$scope.pageSizeSelected = $("#ddPageSize").val();
before $scope.$apply and it worked. Now when i select a value from the field it changes and displays the value i selected.

Display selected items in select box that is stored in database using angularjs laravel

I am trying to get a stored value from the database into a select box, but it is not displaying. The selected value shows in the console(inspect element) but it's just not displaying.
HTML
<td data-ng-class="{'has-error': employeeSchedule.employee.$invalid && employeeSchedule.employee.$dirty}">
<select class="form-control input-sm" name="employee" ng-model="schedule.employee" ng-init="schedule.employee='{{$schedules[0]->employee}}'" ng-options="employee.employeeName for employee in employeesName track by employee.usersId">
<option value="">Select Employee</option>
</select>
</td>
ANGULARJS
app.controller('UpdateWorkScheduleCtrl', [ '$scope', '$http', function ($scope, $http)
{
$http.get('/schedule/employees').success(function(employeedata) {
$scope.employeesName = employeedata;
});
}]);
CONTROLLER(LARAVEL)
public function getEmployees() {
$users = DB::select(DB::raw("SELECT `usersId`, CONCAT(`firstName`,' ',`middleName`,' ',`lastName`) AS employeeName
FROM `users`
WHERE `userStatus` != 'Administrator'
AND `userStatus` != 'Director'
AND `userStatus` != 'HR Specialist'"));
return Response::json($users);
} // end function getEmployees()
INSPECT ELEMENTS(CHROME)
It is clear from inspect elements that the data is there, but it is just not being displayed as the selected item in the select box. Can someone show me what I am doing wrong please.
Your ng-options expression does not match with what you need. You have track by employee.usersId in the syntax employee.employeeName for employee in employeesName track by employee.usersId, Which means that you would need to set ng-model to userId instead of name and also as an object not just as string, i.e your ng-model should ideally be schedule.employee = {usersId:'someid'} for default selection. Now coming to your case which pretty seems like you are trying to set ng-model as a string and you want it the name of the employee (Which probably is a poor choice since you already have an id) you should try the alternate syntax with select as label for value in array`:
ng-options="employee.employeeName as employee.employeeName for employee in employeesName "
Also remember when you use select as syntax you should remove track by, as they are not designed to work together.
Side Note:-
It is a bad idea to use ng-init for initializing ng-mode. And doc says:
The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.

Handling checkboxes and getting values

I'm pretty new to MVC and I'm having a hard understanding how to get the values (basically the IDs) to checkboxes that I'm generating. Here are my checkboxes:
<div id='myCheckboxDiv'>
<input type="checkbox" onclick="checkAll(this)">Check All
#foreach (var form in #Model.DetailObject.DoaFormGroupDocuments)
{
<br>
var checkBoxId = "chk" + form.DocumentId;
#Html.CheckBox(checkBoxId, new { value = form.DocumentId, #checked = true });
#form.DocumentName;
}
</div>
Essentially what I want to do is get the ID to which ever checkbox is checked and save it in to a list after I click a save button at the bottom of the page.
I have run across something like this to handle everything but I'm not quite sure how to use it really...
var values = $('#myCheckboxDiv').find('input:checkbox:checked').map(function () {
// get the name ..
var nameOfSelectedItem = this.attr('name');
// skip the ‘chk’ part and give me the rest
return nameOfSelectedItem.substr(3);
}).get();
The only thing you need to think about is the value of the name attribute your checkbox(es) will have. The way you're handling it right now, your post body is going to have a fairly randomized collection of chkN-named parameters, where N is some number. The modelbinder will need something similarly named as a parameter to your action method in order to bind the posted values to something useful. That's a tall order for something that will be some what variable (the DocumentId values).
The best option would be to set up your checkboxes, instead, as a collection, which means giving them names chk[0], chk[1], etc. Then in your action you can accept a parameter like List<string> chk, and that will contain a list of all the values that were posted.

Create a data-persistent select option

I am dynamically populating a select tag with cities in the US.
Depending on which state the user selects, a city select tag gets dynamically populated with cities from that state. The options for the city are created via a js function which does its job just fine. This function is called on the 'onchange' event within the state select html tag.
As it currently works, the entirety of these fields are within a form. Every field is required to be data-persistent, ie the data you type into these fields must be "filled out" after the form has been submitted. All fields currently on the page, except the dynamically filled city field are persistent and work as intended. This is accomplished by creating CF variables in a format like so:
<cfparam name="form.highschoolstate" default="" />
<cfparam name="form.highschoolcity" default="" />
<cfparam name="form.highschool" default="" />
and at each input, a format similar to this:
<select name="highschoolstate" id="highschoolstate" required="required" onchange="stateswitch('highschoolstate')" value="#form.highschoolstate#">
However, there is one kink in the form, the cities that populate my "High school city" field are not data-persistent. I have, for each state, a list of all of the cities in a format like so:
<option value=\"akiachak\">Akiachak</option>
But when (please see the below picture for result) I try to make the data-persistent, using innerHTML (by replacing the contents of the select tag) I get this code that is undesireable.
<option value=\"akiachak\" <cfif form.highschoolcity EQ \"akiachak\">selected=\"selected\"</cfif>>Akiachak</option>
Is there an option available to put this conditional CF statement within my dynamically generated html such that I can have persistent data throughout my entire form?
Function that dynamically changes the select tag:
//Dynamically changes the drop down list when selecting a city/state pair
function stateswitch(id)
{
var myId = id; //ID of the html element we are changing
var stateFlag = false; //This flag turns true when we have selected a state
var highschoolStateFlag = false; //This flag turns true when we have selected a highschool state
var indexInSelect; //Index selected in the select tag
var selectTag1; //Select tag # 1
var selectTag2; //Select tag # 2 that becomes available after select tag # 1 is selected
if(myId == "state")
{
indexInSelect = document.getElementById("state").selectedIndex;
selectTag1 = document.getElementById("state").options;
selectTag2 = document.getElementById("city");
state = selectTag1[indexInSelect].value;
if(selectTag1[0] == "") //If we haven't selected an option before
{
document.getElementById("state").remove(0); //remove the default/null case
stateFlag = true;
}
if(stateFlag)
indexInSelect = indexInSelect - 1; //accounts for offset of default case in indecees to select from
}
else
{
indexInSelect = document.getElementById("highschoolstate").selectedIndex;
selectTag1 = document.getElementById("highschoolstate").options;
selectTag2 = document.getElementById("highschoolcity");
document.getElementById("highschool").disabled = false;
document.getElementById("highschool").placeholder = "Required";
highschoolstate = selectTag1[indexInSelect].value;
if(selectTag1[0] == "") //If we haven't selected an option before
{
document.getElementById("highschoolstate").remove(0); //remove the default/null case
highschoolStateFlag = true;
}
if(highschoolStateFlag)
indexInSelect = indexInSelect - 1; //accounts for offset of default case in indecees to select from
}
selectTag2.disabled = false; //Disable the second select box (because we know at this point we have selected an option for the first one)
switch(selectTag1[indexInSelect].value)
{
case "alabama":
selectTag2.innerHTML="<option value=\"abbeville\" <cfif form.highschoolcity EQ \"abbeville\">selected=\"selected\"</cfif>>Abbeville</option><option value=\"abernant\" <cfif form.highschoolcity EQ \"abernant\">selected=\"selected\"</cfif>>Abernant</option>";
break;
case "ANOTHER_STATE":
selectTag2.innerHTML="etc...<option value=\"...</option>"
break;
//..
}
}
EDIT - SOLUTION:
What I was trying to do was not possible, so I decided on another approach
From the information that you provided I think the problem is with the \ character in the ColdFusion code. You need that to escape the quotation marks for the JavaScript code but not for the ColdFusion code. Try removing those characters from the <cfif> statements in the JavaScript code.
Instead of this:
<cfif form.highschoolcity EQ \"abbeville\">selected=\"selected\"</cfif>
Try this:
<cfif form.highschoolcity EQ "abbeville">selected=\"selected\"</cfif>
You do not need to escape the quotation marks in the ColdFusion code because the ColdFusion server will process that code before it is output to the user's browser.

populate select box on selecting another selectbox

I have two select boxes.Both of them should be populated from database.Second select box should be populated based on the selected option in the first select box.Database connectivity is success and i am able to populate the first select box.But i dont know how to populate second select box based on the first.code i used to populate first select box is,
<select class="weekcombo">
<%
List list= new DataManager().getlist();
for(int i = 0; i < list.size(); i++) {
out.write("<option value=\""+ list.get(i)+ "\">"+ list.get(i));
}
%>
I dont know whether to use servlet or something else for this.
For first select box you can populate values by default like you have mentioned in above code :
<select class="weekcombo" onchange="populateSecValues(this)">
<%
List list= new DataManager().getlist();
for(int i = 0; i < list.size(); i++) {
out.write("<option value=\""+ list.get(i)+ "\">"+ list.get(i));
}
%>
</select>
<select id="secBox" class="weekcombo">
</select>
Javascript :
In urlString you can pass the first select box value like I have passed in below code snippet
function populateSecValues(obj){
// use here ajax call .. which will populate second box data
var firstBoxValue = obj.value;
var urlString ="your_action_url?firstBoxValue="+firstBoxValue ;
$.ajax({
type: "POST",
url: urlString ,
success: function(result) {
console.info("result"+result);
$("#secBox").html(result);
}
});
}
From server populate the values in the form of
<option value ="secBoxValue">secBoxValue</option>
Sagar Dalvi has a good solution. The only way to populate the 2nd select box based on the item selected in the first is with Javascript. This is because, unless you use Javascript, the contents of the 2nd select box would need to be known at page load time - before the user has made any selections.
Using Javascript, the page is ably to dynamically load the options into the 2nd select box when the user makes the selection in the first, using an AJAX call.
The only way round this without using javascript would be to have the form span more than one page, so the second select box is on the next page.