Avoiding repeated select + options in HTML - javascript

I'm writing a page that basically manages a list of things. Each thing is allocated to a person, and the allocation is done by a select box with options for each user in the system. (So changing the select box re-allocates the thing).
So say I have 100 objects in my table, and 150 users in my system. If I just do plain HTML, I'm going to have 15,000 option tags
I'm assuming there must be a better way of doing this. My thoughts so far are to just render the first element, and then user jquery to copy the options to the other ones. Or the other option I guess would be to have the options be populated by AJAX, though that is slightly awkward (I don't have an obvious place that the AJAX could get a list of users in the system from).
Any thoughts would be most welcome :)

How about having some sort of popup for the selection. That way you would only need one instance of the select elemement along with its options tags.
So you would basically have each person in a list, a readonly input field and a small button next to it. If the user clicks this button, the popup appears and lets the user choose the "object". After closing the popup the selection is passed to the inputfield.

How about something like
<form …>
<table>
<thead>
<tr>
<th>col1</th><th>col2</th><th>col3</th>
</tr>
<tr id="editrow" style="display:none">
<td><input type="text"></td>
<td><input type="text"></td>
<td>
<select>
<option value="1">one</option>
<option value="2">two</option>
<option value="3">three</option>
</select>
</td>
</tr>
</thead>
<tbody>
<tr><td>col1</td><td>col2</td><td data-value="1">one</td></tr>
<tr><td>col1</td><td>col2</td><td data-value="2">two</td></tr>
<tr><td>col1</td><td>col2</td><td data-value="3">three</td></tr>
<tr><td>col1</td><td>col2</td><td data-value="1">one</td></tr>
<tr><td>col1</td><td>col2</td><td data-value="2">two</td></tr>
<tr><td>col1</td><td>col2</td><td data-value="3">three</td></tr>
</tbody>
</table>
</form>
bind a click event handler to tbody > tr > td in which you
hide that <tr>
pull the data from its <td> and data-value attributes to populate the input elements in #editrow
if #editrow is in <tbody> show its preceeding <tr>
insert #editrow after the <tr> and make it visible
.focus() the input element of the <td> that got the click-event
make sure changes made within #editrow are updated in your <tr>'s <td>s accordingly (you should use delegated events for this. then you only need to create and bind the handlers once)
bind a submit event handler to the <form> in which you
walk through tbody > tr to build a data map (javascript object…)
prevent the form from being sent with .preventDefault()
submit the data-map you built in (1) using jQuery.ajax
Or you create <input>s for your <td>s and have the form submit naturally. bulding the map and sending it via ajax is less painful, as you don't need to manipulate hundreds of DOM elements.
This solution will not work without javascript. If it must work without, you won't get around flooding your DOM with hundreds of ever-repeating <select>s.

Related

How to conditionally change column to textbox in AngularJS grid?

I want to know how to add one particular column value as textbox in an AngularJS grid.
So, I am implementing an AngularJS grid as below:
<div>
<table>
<tr>
<th>
<td>Customer Account Number</td>
<td>Customer Name</td>
</th>
</tr>
<tbody>
<tr ng-repeat="item in data">
<td>{{item.CustomerAccNumber}}</td>
<td>{{item.CustomerName}}</td>
</tr>
</tbody>
</table>
<input type=button value="Add Row" ng-click="Add()"/>
So, in scenario 2 things happen:
By default I am getting few records as "Customer Account Number" and "Customer Name".
But there is an "Add Row" button on the same page I need to implement which adds a new row to the grid.
The first column "Customer Account Number" is a text box and second row is noneditable.
So, how to place textbox as a column only when adding a new row from button?
Let's say after adding add row my first column is coming as text box, so after entering the account number in the textbox on textchange it should fetch the customer account number and display it in the same row.
Can someone help me figure out how to put the textbox into one particular column in grid?
Can it be done the way I have implemented the grid?
I don't want to use nggrid.
I would do something like this:
First, in your Controller, in your Add() function, when you push a new row, add a field such as isEditable to allow you to differentiate between a newly added row in the UI.
$scope.Add = function() {
$scope.data.push({
'CustomerAccNumber': 1,
'CustomerName': '',
'isEditable': true // field to identify new row
})
}
Then in your markup, having that flg available, you can leverage ngIf, like so:
<tr ng-repeat="item in data">
<td ng-if="!item.isEditable">{{item.CustomerAccNumber}}</td>
<td ng-if="item.isEditable">
<input type="text" ng-model="item.CustomerAccNumber">
</td>
<td>{{item.CustomerName}}</td>
</tr>
it should fetch CustomerAccount number
As far as your third item, you can use ngBlur to make a call when the user clicks out of the box:
1) Define a function in your controller to call when the user leaves the box.
$scope.doSomethingWithAccNumber() {
// $http call, etc
}
2) Update your textbox to use the ngBlur directive that will trigger when the user clicks out.
<td ng-if="item.isEditable">
<input type="text"
ng-model="item.CustomerAccNumber"
ng-blur="doSomethingWithAccNumber()">
</td>
If you want other keys to trigger this, you can use ngKeydown as well. Use of this is outlined well here. For example, you would want to add ng-keydown="$event.keyCode === 13 && doSomethingWithAccNumber()" to your input to trigger on Enter.

</form> being automattically added to my HTML in the wrong place

I have a page that I would like the following:
a <form action POST>
select List1 - with onchange set populate list 2
select List2 populated using JavaScript <div id="secondList"></div>
with an <input type="submit" value="Assign">
close the </form>
The second populates list fine. The problem seems to be (when checked in FireBug) that the /form tag is moved for some reason so that the order appears like this:
<form action POST> </form>
select list 1 - correct
list 2 - correctly populated
the <input type="submit" value="Assign">
Why does this happen and how can get around this problem?
HTML CODE
<tr>
<form action="webiste/assignToDepartment.php" method="post">
<td>
<select selected="All" name="firstItem" onchange="checkTeacherList(this.value)">
<option value="item1">item1</option>
<option value="item2">item2</option>
<option value="item3">item3</option>
</select>
</td>
<td>
<div id="secondList"></div>
</td>
<td>
<input type="submit" value="Assign">
</td>
</form>
</tr>
Your <form> element has to be placed inside the <td> item. <td> and <th> are the only valid children of <tr>. Alternatively, since your form spans several columns, you'll need to wrap the form around the containing <table>, something like:
<form>
<table>
</table>
</form>
your form element should be placed inside the tag or around the entire table
make your html proper like this
<form action="webiste/assignToDepartment.php" method="post">
<table>
<tr>
<td>
<select selected="All" name="firstItem" onchange="checkTeacherList(this.value)">
<option value="item1">item1</option>
<option value="item2">item2</option>
<option value="item3">item3</option>
</select>
</td>
<td>
<div id="secondList"></div>
</td>
<td>
<input type="submit" value="Assign">
</td>
</tr>
</table>
</form>
Firebug's HTML pane does not show the raw HTML sent by the server. Instead, it shows a nice tree graph with the structure of the document and that tree is built with the memory representation of the document nodes. It's not possible to build an invalid tree, thus invalid HTML needs to be fixed or ignored.
If you pass your HTML through the W3C HTML Validator (you might need to check the "Validate HTML fragment" option if you don't provide the complete document) you'll see it reports several errors about the document structure:
document type does not allow element "XXXX" here
end tag for "XXXX" which is not finished
You need to fix that to ensure proper rendering and, as a consequence, proper scripting.
P.S. While there're normally exact specs on how to process valid HTML, invalid HTML is often left to the browser's discretion. That's a good reason to avoid invalid tags: there can be drastic differences in the way they're rendered by different browsers.

Where do you put the form element if you have editable rows of a table in AngularJS?

We have a table(A) and we want a specific row to become editable on click. Currently we have a directive that inserts a new table into the td of table(A) where it is called. We do this so we can use the <form> element around the table.
uneditable-table.html
<table>
<tbody>
<tr>
<td ng-show="editing" class="editing" colspan="2">
<div edit-form-directive
model="thing"
on-success="thingUpdated(thing); editing=false;"
on-cancel="editing=false; setUpdating(false);"
enabled="editing" />
</td>
</tr>
</tbody>
</table>
edit-template.html inserted via the editFormDirective
<form ng-submit="save(thingCopy)" name="EditForm">
<table>
<tbody>
<tr>
<td>
<input ng-model="thing.field1"/>
</td>
<td>
<input ng-model="thing.field2"/>
</td>
</tr>
</tbody>
<table>
</form>
Question:
We have tried putting the <form> element around each row to be editable, and this works, however, this is not semantically correct with the <form> around a <tr> within a table.
We also considered putting the <form> around the entire table in uneditable-table.html. This causes a form validation issue, where we may have many errors per non-unique form node, so we would have to index the nodes to get specific errors.
We settled on the code as it is here, with having the <form> element around a whole new table (in edit-template.html) and inserting that into a <td>, as this seemed the least harmful.
We do have to have the form tag so we can access validation based on the form name and nodes.
Is there a more Angular (or elegant) way to do this?
Thank you!
Angular way. Form tag isn't needed:
<table ng-form="EditForm">
...
</table>
http://docs.angularjs.org/api/ng.directive:ngForm

Removing duplicates and not valid entries from a select box, but not refreshing the whole box

I'm trying to write a web form, which will have selectable options based on users input from earlier in the form.
Where I'm getting stuck is;
I have a table room types, which is just td tags with input tags (type=text). These are filled in by a user, so I've no idea what they are..
I've got a button to add extra lines to this table (Jquery to add another td tag and input tag)
Users add as many lines as needed
The next part of the form is to fill in Rooms, and select the type for each room. The table layout is the same (except there are two columns, rather than one), and extra lines are added via another button with Jquery.
What I'd like to be able to do, is for new lines added to have two columns in the table. One input text field, and the other a select box with options taken from the table above.
I've managed to get this working to a point. But as users may go back to edit options from the original (room types) table, I need the select boxes to adjust their values based on what the original table currently says.
I can get this working by emptying and re-populating my select boxes everytime one of the input fields accessed (using OnBlur, which is probably not the most effective way to do this), but since it removes entries from the bxes, and then re-populates, any of the select boxes that have been populated already get reset. I only want invalid options (i.e. values that do not exist in the original table) to be reset.
I've been looking/playing at this for a long time now, but my programming abilities are only what I've taught from here and google, whilst messing around on a few very small things before...
My HTML code as it stands (well, part of my code, I've removed all the irrelevant code to keep it simple) is here:
<div id="rm_types_info">
<table id="room_types_table">
<tr>
<td><input type="text" class="room_types" onblur="edit_rooms_select();" /></td>
</tr>
</table>
<button type="button" onclick="rmtypes('room_types_table');">Add Another Room Type</button>
</div>
<div id="rooms_info">
<table id="rooms_table">
<tr>
<th>Room Number</th>
<th>Room Type</th>
</tr>
<tr>
<td><input type="text" /></td>
<td>
<select class="room_type_select">
<option value="Please Choose">Please Choose</option>
</select>
</td>
</tr>
</table>
<button type="button" onclick="rooms('rooms_table');">Add Another Room</button>
</div>
and my JQuery is;
<script>
var userscounter=2
var rmtypescounter=1
var roomscounter=2
function users(ID){
document.getElementById(ID).insertRow(userscounter).innerHTML = '<td><input type="text" /></td><td><input type="text" /></td>';
userscounter++;
};
function rmtypes(ID){
document.getElementById(ID).insertRow(rmtypescounter).innerHTML = '<td><input type="text" class="room_types" onblur="edit_rooms_select();" /></td>';
rmtypescounter++;
}
function rooms(ID){
document.getElementById(ID).insertRow(roomscounter).innerHTML = '<td><input type="text" /></td><select class="room_type_select"><option value="Please Choose">Please Choose</option></select></td>';
roomscounter++;
};
function edit_rooms_select(){
var roomtypelist = $('.room_type_select');
roomtypelist.empty()
$('#room_types_table tr td input').each(function(){
var text = $(this).val();
roomtypelist.append('<option value='+text+'>'+text+'</option>');
});
}
</script>
I've removed the Jquery that was removing the duplicates, since it was definately not working how it needs to...
I'm aware that I may be going about this completely the wrong way, and if using td tags or inputs etc is completely wrong, I'm happy to change the whole form it necessary.
I'm sure this isn't the most effective way to do what I need, but this is how I managed to get it to work...
My HTML...
<div id="rm_types_info">
<table id="room_types_table">
<tr>
<td><input type="text" name="2" class="room_types" onblur="edit_rooms_select();" /></td>
</tr>
</table>
<button type="button" onclick="rmtypes('room_types_table');">Add Another Room Type</button>
</div>
<div id="rooms_info">
<table id="rooms_table">
<tr>
<th>Room Number</th>
<th>Room Type</th>
</tr>
<tr>
<td><input type="text" /></td>
<td>
<select class="room_type_select" id="room_type_select1" >
<option value="1">Please Choose</option>
</select>
</td>
</tr>
</table>
<button type="button" onclick="rooms('rooms_table');edit_rooms_select();">Add Another Room</button>
</div>
And the JQuery scripts relevant. In particular, it was the final function "edit_rooms_select()", and specifically the "Add new options to each select" that I was struggling with.
<script>
var rmtypescount=3;
var room_type_select_count=2;
function rmtypes(){
$('#room_types_table tr:last').after('<tr><td><input type="text" name='+rmtypescount+' class="room_types" onblur="edit_rooms_select();" /></td></tr>');
rmtypescount++;
};
function rooms(){
$('#rooms_table tr:last').after('<tr><td><input type="text" /></td><td><select id="room_type_select'+room_type_select_count+'" class="room_type_select"><option value="1">Please Choose</option></select></td></tr>');
room_type_select_count++
};
function edit_rooms_select(){
$('#room_types_table tr td input').each(function(){
var name = $(this).attr('name');
var value = $(this).val();
//Add New Options to each select
$('#rooms_table select').each(function(){
var last = $(this).children('option:last').val();
if (name > last) {
$(this).append('<option value="'+name+'">'+value+'</option>');
};
});
//Change any room types that have been edited
$('.room_type_select option').each(function(){
var match = $(this).val();
if(name == match){
$(this).text(value)
};
});
//Remove Blank Entries
if(value == ''){
$('.room_type_select option[value='+name+']').remove();
};
});
};
</script>
I think that the edit_rooms_select function is much more expensive than it needs to be. For what I require, this isn't going to be a problem, but I would be very interested to see how other people suggest the lists are edited, following my requirements..
- All user inputs from the room_types_table must be options in the select boxes in the rooms_table
- Any input changed in the room_types_table must have its relevant option in the select boxes changed to match
- Any input that is left blank (or later deleted) from the room_types_table must be removed from the select boxes
- Any select box that has a selection which is then removed from the room_types_table must be reset back to its original "Please Choose" option.
If anyone can suggest better ways to do this, or can tidy my code in any way, I'd like to see the code, and also have it explained, as I'm very inexperienced with Javascript/Jquery.

sending the elements of a select form to another one

it's my first post here and I so sorry if I wrong the place.
My difficulty is view the elements of the first select form to the other one if the first form is set as array.
The goal is to send the elements of a select form to another one and then record them on a db MySQL, that will show them on a html page.
I found in this forum the procedure how to create two select form and add 'n remove the items, then with the command .implode of MySQL can join the element and insert multiple items on db and view them on page.
But if I set the name's select form as array it doesn't work. I've used the following script to have two select form :
<script language="javascript">
function getOpt(select1,select2)
{
for (bCnt=0;bCnt<select1.length;bCnt++)
{
if (select1.options[bCnt].selected)
{
newOpt=new
Option(select1.options[bCnt].text,select1.options[bCnt].value,false,false);
select2.options[select2.length]=newOpt;
}
}
}
function remOpt(select2)
{
for (bCnt=0;bCnt<select2.length;bCnt++)
{
if (select2.options[bCnt].selected)
select2.options[bCnt]=null;
}
}
</script>
then the selects form:
<table border="0">
<tr>
<td>
<label for="id">List:<br></label>
<select name="oneS" id="select_role" size=20 required multiple="multiple"/>
<option value="101">101</option>
<option value="102">102</option>
<option value="103">103</option>
<option value="104">104</option>
<option value="105">105</option>
<option value="106">106</option>
</select>
</td>
<td>
<input type="button" value="Add"onClick="getOpt(this.form.oneS,this.for m.twoS)"><br>
<input type="button" value="Remove"onClick="remOpt(this.form.twoS)">
</td>
<td>
<label for="id">Members List:<br></label>
<select name="twoS" id="select_role" size=20 multiple="multiple"/>
</select>
</td>
</tr>
</table>
if comment the script,the part of the buttons, the second form and change the line:
<select name="oneS" id="select_role" size=20 required multiple="multiple"/>
in
<select name="oneS[]" id="select_role" size=20 required multiple="multiple"/>
I have any issue, can record the items of the first select form on db and view them on the page.
But it's not my goal, I've have to use 2 select form.
Is there some one can help me? thanks a lot.
I've you use jQuery, here it is:
$(document).ready(function()
{
$('.add').click(function(event)//this is your first form, with the id "select_role"
{
$('#select_role2).html($(this).html()+"add whatever html code you want to insert into here");
});
});
use the same idea for remove item.
then use an $.ajax or $.post to send the data to mysql or use a variable to store all the html that was added or removed from your second select.
Simply include the jQuery library and you are all sorted. I have not written raw JAvascript in a long long time, but this will work with the help of jQuery. don't use the same id for two elements again. The id must be unique.
Then assuming you insert a whole bunch of options, you can use $('#your_form_id).serialize() within an $.ajax call to get the array of elements then use the PHP technique for parsing name="insertedoption[]" />. I'm not completely sure I helped you too much, as you need to read up on a few things, but this is an idea on how to do what you need to do.

Categories