I am trying to create a list item with JavaScript, but have been having problems.
To try to simplify things, I created a simple list called "Test List" with one column, "Title" and created a script manager web part on the DispForm.aspx as follows:
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" >
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="/Style%20Library/scripts/SharepointJSOM.js" type="text/javascript" ></script>
<script src="/Style%20Library/scripts/AddFakeItem.js" type="text/javascript" ></script>
<div id="addFakeButton">
<button type="button" class="btn btn-info btn-small" id="btnAddFake"
onclick="AddFakeItem()">Add fake item</button>
</div>
which refers to AddFakeItem.js which is based on stock MS code:
var list;
var loops = new Date();
$(function () {
$("button#btnAddFake").click(AddFakeItem());
});
function AddFakeItem(s, e) {
ExecSPObjModel(AddFake, s, e);
}
function AddFake(s, e) {
if (!SP.ClientContext)
throw {
name: 'Context Null Exception',
message: 'SP.ClientContext has not loaded.'
}
var ctx = SP.ClientContext.get_current();
//list = ctx.get_web().get_lists().getByTitle("Test List");
list = ctx.get_web().get_lists().getById(_spPageContextInfo.pageListId);
if (!list) {
alert("List not found");
return;
}
var itemCreateInfo = new SP.ListItemCreationInformation();
this.newItem = list.addItem(itemCreateInfo);
this.newItem.set_item("Title","Fake Item #" + ++loops);
ctx.load(this.newItem);
if ((1, eval)("this").newItem !== this.newItem)
(1, eval)("this").newItem = this.newItem;
ctx.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
if (this.newItem)
alert('Item created: ' + this.newItem.get_id());
else if ((1, eval)("this").newItem)
alert('Item created: ' + (1, eval)("this").newItem.get_id());
else
alert('No item returned');
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
when I click the button, the script executes, but when it hits .executeQueryAsync, I get
Uncaught TypeError: Cannot read property 'apply' of undefined
What am I doing wrong? Neither of the event handlers execute.
EDIT: Here is the working version of John-M's code from below:
function createListItem(listId) {
// I'm going to keep all of the variables within this function's scope;
// including the callback functions so that they have access to the calling
// function's variables
var cc = SP.ClientContext;
var clientContext = cc.get_current();
var oList = clientContext.get_web().get_lists().getById(listId);
var itemCreateInfo = new SP.ListItemCreationInformation();
var oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', 'New item!' + ++loops);
oListItem.update();
clientContext.load(oListItem);
clientContext.executeQueryAsync(onCreateListItemSuccess, onCreateListItemFailed);
function onCreateListItemSuccess() {
alert('Item created: ' + oListItem.get_id());
}
function onCreateListItemFailed(sender, args) {
alert('createListItem request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
}
var key = "sp.runtime.js";
var namespace = "SP.ClientContext";
SP.SOD.executeFunc(key, namespace, function () {
console.log(key + ": Type available (" + namespace + ")");
}, false);
SP.SOD.executeOrDelayUntilScriptLoaded(function () {
// then you can come wire up this function to your button
$("#btnAddNewCode").click(function () {
createListItem(_spPageContextInfo.pageListId);
});
}, key);
the last part is the details of was needed to get SP.SOD.executeOrDelayUntilScriptLoaded working so that I didn't have to rely on ExecSPObjModel.
(1, eval)("this"). But you did not get that from the MSDN examples, Who taught you this? Because (in this code) is the same aswindow.newItem =ExecSPObjModel, since it looks like you would have to use apply to call yourAddFakefunction -- What are you trying to accomplish jumping through all theevalandapplyindirection hoops anyway? In a function delegate (like you've created based on the MSDN example you can just usethis.newItemsince you already have the calling function forthisExecSPObjModelbecauseFunction.createDelegatealso usesapplyinternally.. try callingAddFakedirectly from the onclick or from withinAddFakeItemthis.onQuerySucceededisundefined. I say clean up your script, strip all that cruft. And I advice to make it work as a Chrome Snippet first; much easier to debug. Andmyfunc.bind(this)is modern ES5 code for oldschoolFunction.createDelegate(this, myfunc)