Issue with relation when creating record - google-app-maker

I have two tables that are related as follows:
PMLprojects ONE - MANY Inovice_stat
I have a script to create a record in the Invoice_stat table. It goes as follows:
var myProjectList = app.datasources.PMLprojects;
var myProjectListID = myProjectList.Id;
var myDatasource = app.datasources.Invoice_stat;
var myCreateDatasource = myDatasource.modes.create;
now = new Date();
var draft = myDatasource.modes.create.item;
draft.EmailStatus = "Yes";
draft.PaidStatus = "No";
draft.DateCreate = now;
myCreateDatasource.createItem(function(newRecord) {
var key = newRecord._key;
});
myDatasource.saveChanges();
All the fields are properly populates except the relation to PMLprojects. How can I related the record from Invoice_stat to PMLprojects? I'm getting the following message:
Error log :
com.google.apps.appmaker.client.datasource.AbstractModelDataSource
WARNING: Could not select element with key RecordKey{key=private$6,
model
key=1Y8Ijd68IZyWFllY3d_C9fhAOFtVgKCtH|Gu5LnmmFmZHfEbrL5Ug1fybNaVLSEPn6}.
No records bound.

Here is some proposed edited code for you to try. However, do remember that if your PMLprojects datasource is not loaded on the client, then this will still fail. I also highly recommend that you check out the official documentation here https://developers.google.com/appmaker/models/relations#modify_associations.
var myProjectList = app.datasources.PMLprojects.item; //change this line to point to an item in the datasource
//var myProjectListID = myProjectList.Id; This line is not necessary
var myDatasource = app.datasources.Invoice_stat;
var myCreateDatasource = myDatasource.modes.create;
now = new Date();
var draft = myCreateDatasource.item; //you already declared the create mode
draft.EmailStatus = "Yes";
draft.PaidStatus = "No";
draft.DateCreate = now;
draft.YourRelationToPMLprojects = myProjectList; //here is where you create your relation, replace YourRelationToPMLprojects with your actual relation name should show up in code autocomplete
myCreateDatasource.createItem(function(newRecord) {
var key = newRecord._key;
});
myDatasource.saveChanges();

Since you are probably using both tables with the Manual Save mode... then #MarkusMalessa's approach might return you an error. If that is so, you have to make sure that you create the relation after you create the item but before you save changes. For that, take into consideration the following example:
var project = app.datasources.PMLprojects.item; //project item
var ds = app.datasources.Invoice_stat;
var createDs = ds.modes.create;
var draft = createDs.item;
draft.EmailStatus = "Yes";
draft.PaidStatus = "No";
draft.DateCreate = new Date();
createDs.createItem(function(){
ds.item.PMLproject = project; //here is where you create your relation
ds.saveChanges();
});
Just remember, this will only work as long as the PMLprojects datasource has already been loaded, otherwise you will probably get an error.

Related

Dynamically creating ASP.NET form controls

I have a form which, based on the answers given in the prior page, can have about 10 different variations in the combination of fields (most are the same, but several change). I decided rather than making 10 separate pages, I would try to make it dynamic. Eventually this will pull the form setup from a database, but for now I'm just trying to get the dynamic part to work. The following code kinda works, but it's giving me a weird result.
private void AddTestControls()
{
var newbox = new TextBox();
newbox.ID = "FirstBox";
newbox.Text = "This is dynamic";
newbox.CssClass = "stepHeader";
DynamicDiv1.Controls.Add(newbox);
var newlit = new Literal();
newlit.ID = "FirstLit";
newlit.Text = ".<br/>.";
DynamicDiv1.Controls.Add(newlit);
newbox.ID = "SecondBox";
newbox.Text = "This is also dynamic";
newbox.CssClass = "step";
DynamicDiv1.Controls.Add(newbox);
}
I've stepped through it and all the properties are getting set correctly, but when the page finally renders, only the SecondBox control is visible. There is no trace of the FirstBox. If I change it so that SecondBox is its own object (newebox2 for example) then both are visible, but with how I was thinking that I would ultimately do the form from the database, this could complicate things. I don't understand why the textbox object has to be recreated in order to add it to the Div's collection of controls. Am I going about this all wrong, or just missing a step somewhere?
Your "SecondBox" are overwriting the "FirstBox" newbox since it's still holding a reference to it. Create a new TextBox for the second box:
var newbox = new TextBox();
newbox.ID = "FirstBox";
newbox.Text = "This is dynamic";
newbox.CssClass = "stepHeader";
DynamicDiv1.Controls.Add(newbox);
var newlit = new Literal();
newlit.ID = "FirstLit";
newlit.Text = ".<br/>.";
DynamicDiv1.Controls.Add(newlit);
// Create a new TextBox
var secondBox = new TextBox();
secondBox.ID = "SecondBox";
secondBox.Text = "This is also dynamic";
secondBox.CssClass = "step";
DynamicDiv1.Controls.Add(secondBox);
I'm not quite sure why this could complicate things, but what you could do is create a method for creating a textbox, if that's easier:
TextBox CreateTextBox(string id, string text, string cssClass)
{
var box = new TextBox();
box.ID = id;
box.Text = text;
box.CssClass = cssClass;
return box;
}
And then
var newBox = CreateTextBox("FirstBox", "This is dynamic", "stepHeader");
DynamicDiv1.Controls.Add(newBox);
What's how it suppose to work. newbox1 is a reference so after the first time it's added to DynamicDiv1, it's there and if you change its Text, then the Text will be changed. You may find this SO useful. This SO demostrates the same issue you are having.

How to search content inside source tab of a rich text field in Tridion

I am currently using the following code to search within Tridion. It is fetching the Items (Components and Pages) based on the input.
Question: In rich text field we have Design,Source and Preview tabs. The below code is searching for content present in Design tab only. I need the Source tab content also
to be considered while performing search.
CoreServiceSession client = new CoreServiceSession();
SessionAwareCoreServiceClient csClient = client.GetClient();
var find = new SearchQueryData
{
Description = "Universe"
ItemTypes = new ItemType[] { ItemType.Page, ItemType.Component }
);
IdentifiableObjectData[] foundItems = csClient.GetSearchResults(find);
Did you try with FullTextQuery
CoreServiceSession client = new CoreServiceSession();
SessionAwareCoreServiceClient csClient = client.GetClient();
ReadOptions readoption = new ReadOptions();
var find = new SearchQueryData
{
Description = "Universe"
FullTextQuery= "Universe"
ItemTypes = new ItemType[] { ItemType.Component }
);
IdentifiableObjectData[] foundItems = csClient.GetSearchResults(find);
As FullTextQuery can impact on your CMS performance, you may want it to restrict to particular schema components field only.
BasedOnSchemaData basedSchemaNote = new BasedOnSchemaData();
basedSchemaNote.Schema = new LinkToSchemaData() { IdRef = "tcm:XX-xxxx-8" };
basedSchemaNote.Field = "FieldName";
basedSchemaNote.FieldValue = "*SeachText*";

Get List of Localized Items

I need to get the list of localized items of a publication programatically using coreservice in tridion. Could any one suggest me.
I would use the GetListXml method and specify a BluePrintChainFilterData filter object.
var subjectId = "[TCM Uri of your item]";
var filter = new BluePrintChainFilterData
{
Direction = BluePrintChainDirection.Down
};
var subjectBluePrintChainList = coreServiceClient.GetListXml(subjectId, filter);
You then still need to verify the localized items from the received list.
This wasn't in my original answer, and probably isn't complete because I don't take into account namespaces, but the following would work to select the localized (not shared) items.
var localizedItems = subjectBluePrintChainList.Elements("Item")
.Where(element => "false".Equals(element.Attribute("IsShared").Value, StringComparison.OrdinalIgnoreCase));
The only way I know is to use search functionality:
var searchQuery = new SearchQueryData();
searchQuery.BlueprintStatus = SearchBlueprintStatus.Localized;
searchQuery.FromRepository = new LinkToRepositoryData{IdRef = "tcm:0-5-1"};
var resultXml = ClientAdmin.GetSearchResultsXml(searchQuery);
var result = ClientAdmin.GetSearchResults(searchQuery);

ArrayCollection removing sort

After applying a numeric sort to my dataprovider(Array Collection), I can not reorder the items via a tilelist. Do I need to remove the sort from the arrayCollection. If so, is it just a case of setting collection.sort = null ?
var sortField:SortField=new SortField();
sortField.name="order";
sortField.numeric=true;
var sort:Sort=new Sort();
sort.fields=[sortField];
Setting the sort to null should indeed remove the sort for the collection. You might need to do an optional refresh().
I got caught with this problem too, I found your question, and I still didnt get it solved like Christophe suggested.
After suffering with this for a while, I discovered one way to avoid the problems you mentioned.
Simply use an auxiliary ArrayCollection to do the sort. Anyway your Sort instance seems to be temporary (you want to through it away), so why not use a temporary ArrayCollection?
Here's how my code looked like:
// myArrayCollection is the one to sort
// Create the sorter
var alphabeticSort:ISort = new Sort();
var sortfieldFirstName:ISortField = new SortField("firstName",true);
var sortfieldLastName:ISortField = new SortField("lastName",true);
alphabeticSort.fields = [sortfieldFirstName, sortfieldLastName];
// Copy myArrayCollection to aux
var aux:ArrayCollection = new ArrayCollection();
while (myArrayCollection.length > 0) {
aux.addItem(myArrayCollection.removeItemAt(0));
}
// Sort the aux
var previousSort:ISort = aux.sort;
aux.sort = alphabeticSort;
aux.refresh();
aux.sort = previousSort;
// Copy aux to myArrayCollection
var auxLength:int = aux.length;
while (auxLength > 0) {
myArrayCollection.addItemAt(aux.removeItemAt(auxLength - 1), 0);
auxLength--;
}
It's not the neatest code, it has some weird hacks like auxLength instead of aux.length (this one gave me -1 array range exception), but at least it solved my problem.
Source
Adobe Flex - Sorting an ArrayCollection by Date
/**
* #params data:Array
* #return dataCollection:Array
**/
private function orderByPeriod(data:Array):Array
{
var dataCollection:ArrayCollection = new ArrayCollection(data);//Convert Array to ArrayCollection to perform sort function
var dataSortField:SortField = new SortField();
dataSortField.name = "period"; //Assign the sort field to the field that holds the date string
var numericDataSort:Sort = new Sort();
numericDataSort.fields = [dataSortField];
dataCollection.sort = numericDataSort;
dataCollection.refresh();
return dataCollection.toArray();
}

ADO.NET Data Services: Non-Asynch Calls?

I have a question that I'm struggling with in ADO.NET Data Services:
When assembling an Entity for storage I need to get a related value from a lookup file. For example a person has a status code assigned of 'Pending' which is in a table called StatusCodes.
In Entity Framework, I'd need to set the value of person.StatusCode equal to an instance of the StatusCode. In the Entity Framework or in LINQ2Sql I'd so something like this:
var person = Person.CreatePerson(stuff);
var statCode = myContext.StatusCodeSet.Where(sc => sc.Description == "Pending").FirstOrDefault();
person.StatusCode = statCode;
// ...more code here...
myContext.BeginSaveChanges(SaveChangesOptions.Batch,
new AsyncCallback(OnSaveAllComplete),
null);
The query for the statCode won't work in ADO.NET Data Services and I get a runtime error saying the function is not supported. I assume it's because the statCode lookup is not an Async call.
However,
var person = Person.CreatePerson(stuff);
var query = from stat in myContext.StatusCodeSet
where stat.Description == "Pending"
select stat;
var dsQuery = (DataServiceQuery<StatusCode>)query;
dsQuery.BeginExecute(
result => tutorApplication.StatusCode = dsQuery.EndExecute(result).FirstOrDefault(), null);
// ...more code here...
myContext.BeginSaveChanges(SaveChangesOptions.Batch,
new AsyncCallback(OnSaveAllComplete),
null);
doesn't work either due to the Async nature of the query, the result won't be back before the person save happens.
Am I approaching this correctly?
Thanks
After sleeping on this I came up with the following:
var person = Person.CreatePerson(stuff);
var appStatPending = new StatusCode()
{
StatusCodeId = (int)StatusCodes.Pending,
Code = "Pending",
Description = "Pending",
EffectiveDate = DateTime.Now,
EnteredBy = "",
EnteredDate = DateTime.Now
};
myContext.AttachTo("StatusCodeSet", appStatPending);
person.StatusCode = appStatPending;
myContext.SetLink(tutorApplication, "StatusCode", appStatPending);
// ...more code here...
myContext.BeginSaveChanges(SaveChangesOptions.Batch,
new AsyncCallback(OnSaveAllComplete),
null);
I can create a local copy of the status code and link it into the context. It's important to new up the appStatPending rather than doing a StatusCode.CreateStatusCode() since doing that will add a new StatusCode to the database when the person graph persisted. For the same reason it's important to do the AttachTo("StatusCodeSet", appStatPending) since doing myContext.AddToStatusCodeSet() will also add a new entry to the StatusCodes table in the database.

Resources