I have created a Parent List that has a multiple selection checkbox for "Media Type". If a user chooses multiple media types, I want user to add a quantity to each media type selected. I am using SharePoint 2010. I am a novice so I am somewhat limited to SPD, InfoPath and using "simple" code of the brilliant SP developers from internet searches. Assistance is appreciated.
2 Answers
The problem is that SharePoint lists work in single rows and don't allow multiple complex sub records for individual items. It's a huge limitation that still exists in 2013 and I can't see anything in the road map that suggests this basic need will be introduced in the next version.
I would advise against InfoPath because it's been deprecated. I would similarly advise against modifying the list form views themselves as this can lead to any number of strange quirks.
You have several client-side options, all of which will require a custom form and use of the JSOM (JavaScript Object Model). You can achieve this using a single list but two would allow you to add a worflow to the Master list that included the media orders created in the second list.
Single list approach (making several assumptions):
- In your list include columns for Customer Name (Peron or Group, or Single Line of Text if not in AD), Order Date (Date and Time), Media (Choice->Checkbox) and Quantity (Number).
- Create a new view and Group by Customer Name, order by Created.
- Create a new page in the same site and name it Orders or whatever is appropriate.
- Add a Script Editor web part to the page and either embed or link to (preferred) your code.
Your code would include a form with Customer Name and Order Date, and a table with a row for each Media Types (and Quantity) underneath. Each row in this table will represent a new item (row) in your list.
Use the ClientContext library to lookup the list. Generate the table above by querying the list's Media field and creating a new row for each value. The Quantity field is just a plain input field.
Use jQuery to iterate over the table rows and create an object array for each row that contains a Quantity. You'd also want to validate these fields to ensure a valid numeric value.
Then just create a new list item for each row returned.
Clearly it's outside the scope of this reply to include fully-functional code without actually building the solution. But the example below should hopefully give you a head start.
<!-- Add reference to jQuery-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
// Variables
$(document).ready(function () {
// Initialise the function after sp.js and ClientContext is ready.
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', GetContextListAndField);
});
// Get context, list and required fields
function GetContextListAndField() {
var ctx;
var list;
var field;
// Get current context
ctx = SP.ClientContext.get_current();
// Get the list
list = ctx.get_web().get_lists().getByInternalNameOrTitle("Orders")
ctx.load(list);
// Get the choice field
field = list.get_fields().getByInternalNameOrTitle("Media");
field = ctx.castTo(field, SP.FieldChoice);
ctx.load(field);
// Execute query
ctx.executeQueryAsync(
Function.createDelegate(this, this.BuildForm),
Function.createDelegate(this, this.onFailure)
);
}
function BuildForm(sender, args) {
var form = $('#myForm');
var clientName = '<p>Full Name: <input type="text" id="name" /></p>';
var orderDate = '<p>Order Date: <input type="text" id="date" /></p>';
var table = $('#myTable');
var submit = '<p><button id="Submit" type="button">Send Order</button></p>';
$('#myForm').append(clientName);
$('#myForm').append(orderDate);
// Build table only if it doesn't already exist
if (!table.length) {
var tableHTML = '<table id="myTable"><tr><th>Media</th><th>Quantity</th></tr></table>';
// Get arry of possible choices
var choices = field.get_choices();
// Populate table
$.each(choices, function (text) {
$('#myTable').append('<tr class="mediaRow"><td class="mediaType">' + text + '</td><td class="mediaVal"><input /></td></tr>');
});
// Append table to form
$('#myForm').append(tableHTML)
}
$('#myForm').append(submit);
$('#submit').click(function() {
createListItems(list);
});
}
function createListItems(list) {
var client = $('#myForm #name');
var date = $('#myForm #date');
var row = $('tr.mediaRow');
var count = 0;
row.each(function() {
var type = $(this).children('.mediaType').text();
var quantity = $(this).children('.mediaVal input').text();
if (quantity !== "") {
var itemCreateInfo = new SP.ListItemCreationInformation();
var listItem = list.addItem(itemCreateInfo);
listItem.set_item(client, date, type, quantity);
listItem.update();
count++;
}
});
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded() {
alert(count + 'items have been added to your order.');
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
function onFailure(sender, e) {
alert('Failed:' + e.get_message() + '\n' + e.get_stackTrace());
}
</script>
<!-- Form placeholder -->
<div id="myForm"></div>
Out-of-the-box having such behavior is not offered by any component. You could however opt for:
- Change the Edit form into an InfoPath and rely on few Action rules and Formatting rules you could decide to toggle visibility on the "Media-Type" to store data, see here to get started http://allcomputers.us/windows_server/infopath-with-sharepoint-2010---use-the-edit-form-on-the-list-page.aspx and here to Show/Hide fields based on conditions http://office.microsoft.com/en-us/infopath-help/hide-or-disable-a-control-based-on-values-in-a-form-HP001096364.aspx
- Customize the EDIT Form to include some JavaScript code to show/hide (see here http://sharepointsherpa.com/2008/08/26/sharepoint-2007-hiding-fields-on-newformaspx-and-editformaspx-the-easy-way/)
In both cases, you should probably create additional columns for each quantity you need to store per record.
-
I believe I understand what you are saying. However, I don't see a way with the above suggestions to fulfil my customers needs. Thank you for your quick response.– Doo4funJan 11, 2013 at 21:23
-
you would need to store data in a custom list, which allows edit forms either custom or InfoPath based - the "window" to your data. the shape of the form is up to you to design (more complex would require Web-Part). Either of the 2 options allows for custom interaction (hide/show various form elements - text boxes, etc.). Jan 12, 2013 at 11:11