Can I set the default value of a custom list column to be a new Guid? - sharepoint

I tried setting the defaultvalue property of the field to Guid.NewGuid() but every item created has the same guid so I guess the Guid.NewGuid() is being stored as the default rather than being run each time.
Is the only way to achieve this to add an event handler to the list for OnAdded?

I'm assuming you're using a Single Line of Text field for this. The standard default for such a field is always a constant, you can't assign a variable or function via the object model. All that would do is assign the static result of that particular call of the function.
While text fields can support a calculated default value, it uses the same functions that are in Calculated columns, which do not support random numbers.
Your best bet is to use an Event Handler, I would recommend ItemAdding over ItemAdded as well. You'd be assigning to properties.AfterProperties["fieldname"] instead of field.DefaultValue, of course.

If you are creating the field through code and setting the field.DefaultValue = Guid.NewGuid(), this will run the Guid.NewGuid() and store the returned Guid as the default
It is the equlivant of running the folowing code:
Guid newGuid = Guid.NewGuid();
string newGuidString = newGuid.ToString();
field.DefaultValue = newGuidString;
I dont know of any method you can use to set the field to generate a new Guid on item creation other than using an Event handler.
It should be posable to genrate a random number using the field.DefaultValue = "RANDBETWEEN(10,20)"; but i have not tested this

Related

Where is my error with my join in acumatica?

I want to get all the attributes from my "Actual Item Inventry" (From Stock Items Form) so i have:
PXResultset<CSAnswers> res = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem,
On<CSAnswers.refNoteID, Equal<Current<InventoryItem.noteID>>>
>
>.Select(new PXGraph());
But, this returns me 0 rows.
Where is my error?
UPDATED:
My loop is like this:
foreach (PXResult<CSAnswers> record in res)
{
CSAnswers answers = (CSAnswers)record;
string refnoteid = answers.RefNoteID.ToString();
string value = answers.Value;
}
... but i can not go inside foreach.
Sorry for the English.
You should use an initialized graph rather than just "new PXGraph()" for the select. This can be as simple as "this" or "Base" depending on where this code is located. There are times that it is ok to initialize a new graph instance, but also times that it is not ok. Not knowing the context of your code sample, let's assume that "this" and "Base" were insufficient, and you need to initialize a new graph. If you need to work within another graph instance, this is how your code would look.
InventoryItemMaint graph = PXGraph<InventoryItemMaint>.CreateInstance<InventoryItemMaint>();
PXResultset<CSAnswers> res = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<CSAnswers.refNoteID, Equal<Current<InventoryItem.noteID>>>>>
.Select(graph);
foreach (PXResult<CSAnswers> record in res)
{
CSAnswers answers = (CSAnswers)record;
string refnoteid = answers.RefNoteID.ToString();
string value = answers.Value;
}
However, since you should be initializing graph within a graph or graph extension, you should be able to use:
.Select(this) // To use the current graph containing this logic
or
.Select(Base) // To use the base graph that is being extended if in a graph extension
Since you are referring to:
Current<InventoryItem.noteID>
...but are using "new PXGraph()" then there is no "InventoryItem" to be in the current data cache of the generic base object PXGraph. Hence the need to reference a fully defined graph.
Another syntax for specifying exactly what value you want to pass in is to use a parameter like this:
var myNoteIdVariable = ...
InventoryItemMaint graph = PXGraph<InventoryItemMaint>.CreateInstance<InventoryItemMaint>();
PXResultset<CSAnswers> res = PXSelectJoin<CSAnswers,
InnerJoin<InventoryItem, On<CSAnswers.refNoteID, Equal<Required<InventoryItem.noteID>>>>>
.Select(graph, myNoteIdVariable);
foreach (PXResult<CSAnswers> record in res)
{
CSAnswers answers = (CSAnswers)record;
string refnoteid = answers.RefNoteID.ToString();
string value = answers.Value;
}
Notice the "Required" and the extra value in the Select() section. A quick and easy way to check if you have a value for your parameter is to use PXTrace to write to the Trace that you can check after refreshing the screen and performing whatever action would execute your code:
PXTrace.WriteInformation(myNoteIdVariable.ToString());
...to see if there is a value in myNoteIdVariable to retrieve a result set. Place that outside of the foreach block or you will only get a value in the trace when you actually get records... which is not happening in your case.
If you want to get deep into what SQL statements are being generated and executed, look for Request Profiler in the menus and enable SQL logging while you run a test. Then come back to check the results. (Remember to disable the SQL logging when done or you can generate a lot of unnecessary data.)

How do I call NetSuite SuiteTalk inventoryitem add using list name for StringCustomFieldRef value instead of internalID?

When adding a new inventoryitem through the API we have a few list based custom fields we need to fill in. I want to be able to use the string value for the field but when I try to the call errors out.
We have a custom list with two values:
InternalId 1 is "LTL"
InternalId 2 is "FedEx"
I have tried sending the value across as a StringCustomFieldRef and when setting the value to the string value of the "LTL" we get an invalid ref error. When setting the value to the internalId of 1 it works.
I also tried using a SelectCustomFieldRef and when setting the value->name to the string value of "LTL" it errors like we did not pass the value at all. When we set value->internalId to 1 it works.
Is it possible to just pass in the string value?
Does not work:
$customField1 = new StringCustomFieldRef();
$customField1 ->value = "LTL";
$customField1 ->scriptId = 'custitem_zu_zu_fulfill_pref';
Works:
$customField1 = new StringCustomFieldRef();
$customField1 ->value = "1";
$customField1 ->scriptId = 'custitem_zu_zu_fulfill_pref';
This is the error response:
<platformCore:statusDetail type="ERROR">
<platformCore:code>INVALID_KEY_OR_REF</platformCore:code>
<platformCore:message>Invalid custitem_zu_zu_fulfill_pref reference key LTL.</platformCore:message>
</platformCore:statusDetail>
No, unfortunately you cannot set a field with the Name value--you will have to use the internalId. If your custom field is list-based, then you should be using SelectCustomFieldRef or MultiSelectCustomFieldRef.
If you wish to use the Name value, you can perform a CustomListSearchBasic to get the Name and internalId of each item, and match that to your chosen Name.

How to store a list of dates in a multi-value field using SSJS?

In the past, I've added multi-value text data to a field putting the values into a simple JavaScript array. For example:
doc.replaceItemValue('AlwaysAccess', ["John Doe","Bob Smith"]);
Any recommendations on how to store a series of DATES in a multi-value, Time/Date field in a Notes document?
TL;DR: The concept should be almost identical to a multi-value Field of Strings, your Date(/Time) values need to be valid NotesDateTime values properly stored.
A Notes field can have multiple Date/Time values; you can see this in the Form, selecting a field of type Date/Time and checking "Allow multiple values".
You can also see that a multi-value of from the replaceItemValue page of the Domino Designer Knowledge Center.
To accomplish the same with the NotesDominoAPI (in SSJS), we'll need to:
get a handle on the NotesItem (the field, which I'll create)
create our values to put in the field (I'll create a couple using session.createDateTime)
add these values to a java.util.Vector, which will be interpreted as multi-value (you should also be able to use the SSJS Array, if you prefer)
set the values to the field
Sample code (I just ran it in the onClick event of an xp:button):
//create a new doc
var tmpDoc:NotesDocument = database.createDocument();
//give it a Form
tmpDoc.replaceItemValue("Form","MultiDateFieldForm");
//create a NotesItem
var itm:NotesItem = tmpDoc.replaceItemValue("DateFieldName",new java.util.Vector());
//create the Vector, our multi-value container
var vec:java.util.Vector = new java.util.Vector();
//create a couple NotesDateTime values to store
var first = session.createDateTime(new Date());
vec.add(first);
var second = session.createDateTime("Tomorrow");
vec.add(second);
//save the values to the item
itm.setValues(vec);
//save
tmpDoc.save();
//recycle!
first.recycle();
second.recylce();
itm.recycle();
tmpDoc.recylce();
[Edit]
As Frantisek Kossuth points out in the comments, be sure to recycle your NotesDomino API objects (especially the Date/Time ones). I've updated the code to reflect this.
[/Edit]
Checking a Form-based View after running, I'm giving this (field properties reflect the multi-value field of Date/Time values; two shots as it ran out of the box).
Essentially, I found that I needed to create a vector to store the list of dates, and populate it with NotesDateTime objects.
var vRepeatDates:java.util.Vector = new java.util.Vector();
In my case, I needed to increment the dates x amount of times. So, I used a for loop to add the NotesDateTime elements to the vector (while using .adjustDay(1) to increment the dates)
And finally store the vector in a field using replaceItemValue()
doc.replaceItemValue("RepeatInstanceDates",vRepeatDates);

Can't modify/remove a field from an ActivityNode using sbt

I created an ActivityNode (an Entry) and I can add custom fields with the
setFields(List<Field> newListField)
fonction.
BUT
I am unable to modify these fields. (In this case I try to modify the value of the field named LIBENTITE)
FieldList list = myEntry.getTextFields();
List<Field> updatedList = new ArrayList<Field>();
//I add each old field in the new list, but I modify the field LIBENTITE
for(Field myField : list){
if(myField.getName().equals("LIBENTITE")){
((TextField)myField).setTextSummary("New value");
}
updatedList.add(myField);
}
myEntry.setFields(updatedList);
activityService.updateActivityNode(myEntry);
This code should replace the old list of fields with the new one, but I can't see any change in the custom field LIBENTITE of myEntry in IBM connections.
So I tried to create a new list of fields, not modifying my field but adding a new one :
for(Field myField:list){
if(!myField.getName().equals("LIBENTITE")){
updatedList.add(myField);
}
}
Field newTextField = new TextField("New Value");
newTextField .setFieldName("LIBENTITE");
updatedList.add(newTextField );
And this code is just adding the new field in myEntry. What I see is that the other custom fields did not change and I have now two custom fields named LIBENTITE, one with the old value and the second with the new value, in myEntry.
So I though that maybe if I clear the old list of Fields, and then I add the new one, it would work.
I tried the two fonctions
myEntry.clearFieldsMap();
and
myEntry.remove("LIBENTITE");
but none of them seems to work, I still can't remove a custom field from myEntry using SBT.
Any suggestions ?
I have two suggestions, as I had (or have) similar problems:
If you want to update an existing text field in an activity node, you have to call node.setField(fld) to update the field in the node object.
Code snippet from my working application, where I'm updating a text field containing a (computed) start time:
ActivityNode node = activityService.getActivityNode(id);
node.setTitle(formatTitle()); // add/update start and end time in title
boolean startFound = false;
// ...
FieldList textfields =node.getTextFields();
Iterator<Field> iterFields = textfields.iterator();
while (iterFields.hasNext()) {
TextField fld = (TextField) iterFields.next();
if (fld.getName().equals(Constants.FIELDNAME_STARTTIME)) {
fld.setTextSummary(this.getStartTimeString()); // NOTE: .setFieldValue does *not* work
node.setField(fld); // write updated field back. This seems to be the only way updating fields works
startFound=true;
}
}
If there is no field with that name, I create a new one (that's the reason I'm using the startFound boolean variable).
I think that the node.setField(fld) should do the trick. If not, there might be a way to sidestep the problem:
You have access to the underlying DOM object which was parsed in. You can use this to tweak the DOM object, which finally will be written back to Connections.
I had to use this as there seems to be another nasty bug in the SBT SDK: If you read in a text field which has no value, and write it back, an error will be thrown. Looks like the DOM object misses some required nodes, so you have to create them yourself to avoid the error.
Some code to demonstrate this:
// ....
} else if (null == fld.getTextSummary()) { // a text field without any contents. Which is BAD!
// there is a bug in the SBT API: if we read a field which has no value
// and try to write the node back (even without touching the field) a NullPointerException
// will be thrown. It seems that there is no value node set for the field. We
// can't set a value with fld.setTextSummary(), the error will still be thrown.
// therefore we have to remove the field, and - optionally - we set a defined "empty" value
// to avoid the problem.
// node.remove(fld.getName()); // remove the field -- this does *not* work! At least not for empty fields
// so we have to do it the hard way: we delete the node of the field in the cached dom structure
String fieldName = fld.getName();
DeferredElementNSImpl fldData = (DeferredElementNSImpl) fld.getDataHandler().getData();
fldData.getParentNode().removeChild(fldData); // remove the field from the cached dom structure, therefore delete it
// and create it again, but with a substitute value
Field newEmptyField = new TextField (Constants.FIELD_TEXTFIELD_EMPTY_VALUE); // create a field with a placeholder value
newEmptyField.setFieldName(fieldName);
node.setField(newEmptyField);
}
Hope that helps.
Just so that post does not stay unanswered I write the answer that was in a comment of the initial question :
"currently, there is no solution to this issue, the TextFields are read-only map. we have the issue recorded on github.com/OpenNTF/SocialSDK/issues/1657"

Can't set Orchard field values unless item already created

I seem to be having a problem with assigning values to fields of a content item with a custom content part and the values not persisting.
I have to create the content item (OrchardServices.ContentManager.Create) first before calling the following code which modifies a field value:
var fields = contentItem.As<MyPart>().Fields;
var imageField = fields.FirstOrDefault(o => o.Name.Equals("Image"));
if (imageField != null)
{
((MediaLibraryPickerField)imageField).Ids = new int[] { imageId };
}
The above code works perfectly when against an item that already exists, but the imageId value is lost if this is done before creating it.
Please note, this is not exclusive to MediaLibraryPickerFields.
I noticed that other people have reported this aswell:
https://orchard.codeplex.com/workitem/18412
Is it simply the case that an item must be created prior to amending it's value field?
This would be a shame, as I'm assigning this fields as part of a large import process and would inhibit performance to create it and then modify the item only to update it again.
As the comments on this issue explain, you do need to call Create. I'm not sure I understand why you think that is an issue however.

Resources