Thanks for the library!
Would it be possible to make it available on bower?
Support for browserify would also be great.
<Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>3</Value></Eq>
but there is no support to ModStat Value Type. Any good workarounds to change the value type keeping in mind I'm dynamically pushing the Expressions? camlExpressions.push(CamlBuilder.FromXml(CamlBuilder.Expression().IntegerField("_ModerationStatus").EqualTo(3).ToString().replace("Integer", "ModStat")));
doesn't work as FromXml isn't meant for Expressions. var modStat = CamlBuilder.Expression().IntegerField("_ModerationStatus").EqualTo(3);
modStat.builder.tree[2].ValueType = "ModStat";
camlExpressions.push(modStat);
FieldExpression.prototype.ChoiceField = function (internalName) {
return new FieldExpressionToken(this.builder, internalName, "Choice");
};
/** Specifies that a condition will be tested against the field with the specified internal name, and the type of this field is Computed */
FieldExpression.prototype.ComputedField = function (internalName) {
return new FieldExpressionToken(this.builder, internalName, "Computed");
};
var camlQuery = new CamlBuilder().Where() .ModStatField("_ModerationStatus").IsRejected() .ToCamlQuery(); var listItems = context.get_web().get_lists().getByTitle("Documents").getItems(camlQuery); context.load(listItems); context.executeQueryAsync(function() { var e = listItems.getEnumerator(); while (e.moveNext()) { console.log(e.get_current.get_title()); } })
var camlQuery = new CamlBuilder().Where() .ModStatField("_ModerationStatus").IsRejected() .ToCamlQuery(); var listItems = context.get_web().get_lists().getByTitle("Documents").getItems(camlQuery); context.load(listItems); context.executeQueryAsync(function() { var e = listItems.getEnumerator(); while (e.moveNext()) { console.log(e.get_current.get_title()); } })
var context = SP.ClientContext.get_current(); var list = context.get_web().get_lists().getByTitle("Documents"); var camlQuery = new CamlBuilder().Where() .ModStatField("_ModerationStatus").IsRejected() .ToCamlQuery(); var listItems = list.getItems(camlQuery); context.load(listItems); context.executeQueryAsync(function() { var e = listItems.getEnumerator(); while (e.moveNext()) { console.log(e.get_current.get_title()); } })
var context = SP.ClientContext.get_current(); var list = context.get_web().get_lists().getByTitle("Documents"); var camlQuery = new CamlBuilder().Where() .ModStatField("_ModerationStatus").IsRejected() .ToCamlQuery(); var listItems = list.getItems(camlQuery); context.load(listItems); context.executeQueryAsync(function() { var e = listItems.getEnumerator(); while (e.moveNext()) { console.log(e.get_current.get_title()); } })
var context = SP.ClientContext.get_current(); var list = context.get_web().get_lists().getByTitle("Documents"); var camlQuery = new CamlBuilder().Where() .ModStatField("_ModerationStatus").IsRejected() .ToCamlQuery(); var listItems = list.getItems(camlQuery); context.load(listItems); context.executeQueryAsync(function() { var e = listItems.getEnumerator(); while (e.moveNext()) { console.log(e.get_current.get_title()); } })
Simplifies creation of SharePoint CAML queries for client-side scripts. Can be used with either SharePoint Client Object Model or SPServices.
Nuget:
PM> Install-Package CamlJs
TypeScript definitions:
PM> Install-Package camljs.TypeScript.DefinitelyTyped
I created a Chrome extension for instant testing CamlJs queries against real lists,CamlJs-Console. The extension is open source and free. Available via Web Store or alternatively you can install it from the source code (see docs on GitHub).
View element is added! Scope attribute, ViewFields, Joins and ProjectedFields are supported. Joining lists via CamlJs is very easy. Here's the example:
var query = new CamlBuilder() .View(["Title","Country","Population"]) .LeftJoin("Country","Country").Select("People","Population") .Query() .Where() .NumberField("Population").LessThan(10) .ToString();
Intellisense helps understanding the parameters:
And one more screenshot of intellisense:
So as you see, really simple: Join listName as Alias, Select Field as Alias, Select Field as Alias, etc. Then, use fields aliases in the main query. That's it! Corresponding Joins and ProjectedFields elements are generated automatically.
So the resulting generated CAML query will be the following:
<View><ViewFields><FieldRefName="Title"/><FieldRefName="Country"/><FieldRefName="Population"/></ViewFields><Joins><JoinType="LEFT"ListAlias="Country"><Eq><FieldRefName="Country"RefType="ID"/><FieldRefName="ID"List="Country"/></Eq></Join></Joins><ProjectedFields><FieldShowField="People"Type="Lookup"Name="Population"List="Country"/></ProjectedFields><Query><Where><Lt><FieldRefName="Population"/><ValueType="Number">10</Value></Lt></Where></Query></View>
CamlJs was dependent on some SharePoint components (Sys.StringBuilder and SP.XmlWriter). But many people had problems with that, so now CamlJs doesn't have any dependencies.
This enables opportunity to run CamlJs standalone, e.g. in SharePoint Apps without including heavy SP javascripts; and also to use CamlJs in SharePoint 2007. Though please remember that some CAML Query elements (e.g. <In>) were added only in SP2010.
Please remember that some fields were marked as DEPRECATED in Release 2.0. In version 2.5, previously marked LookupIdField is removed. In next versions, the process will be continued.
If you're still using LookupIdField, replace it like this:
Old code example:
Replace with:
Added ToCamlQuery method, that can be to finalize the query. But instead of string, ToCamlQuery will produce a ready-to-use SP.CamlQuery object, which you can then pass into list.getItems method.
Example project is now a SharePoint-hosted app with a simple interactive demo:
UserMultiField and LookupMultiField weren't much tested in previous release, but now in 2.5 they are tested through and significantly improved. Now instead old EqualTo, NotEqualTo, Includes and NotIncludes operations (these are marked DEPRECATED), single operation "IncludesSuchItemThat" added.
So now it is possible to check condition against Id or against a value, cast to a specified type (same as with single-value lookups):
Internally, CAML Query is identical for MultiLookup and single-value Lookup columns, but hopefully this minor syntax improvement will help people better understand how SharePoint interprets this query.
---------------- end of release 2.5 news -------------
To start with, let's assume we need to fetch all Google-related letters from some mailbox list, using SharePoint Client Object Model. To generate the corresponding query using Caml Builder, you could use following javascript code:
var camlBuilder = new CamlBuilder(); var caml = camlBuilder.Where() .TextField("Email").EqualTo("support@google.com") .Or() .TextField("Email").EqualTo("plus@google.com") .Or() .TextField("Title").BeginsWith("[Google]") .Or() .TextField("Content").Contains("Google") .ToString();
This will generate expected CAML:
<Where><Or><Eq><FieldRefName="Email"/><ValueType="Text">support@google.com</Value></Eq><Or><Eq><FieldRefName="Email"/><ValueType="Text">plus@google.com</Value></Eq><Or><BeginsWith><FieldRefName="Title"/><ValueType="Text">[Google]</Value></BeginsWith><Contains><FieldRefName="Content"/><ValueType="Text">Google</Value></Contains></Or></Or></Or></Where>
, which then could be used in SP.CamlQuery.
Very good so far, and have a look at some other examples!
First of all, cannot resist to mention, that CamlBuilder covers almost all Query elements, described at MSDN.
For example, seldom used Membership element:
var caml = camlBuilder.Where() .UserField("AssignedTo").EqualToCurrentUser() .Or() .UserField("AssignedTo").IsInCurrentUserGroups() .GroupBy("ProductTitle") .OrderBy("Priority").ThenBy("Title") .ToString();
This code will generate following CAML:
<Where><Or><Eq><FieldRefName="AssignedTo"/><ValueType="Integer"><UserID/></Value></Eq><MembershipType="CurrentUserGroups"><FieldRefName="AssignedTo"/></Membership></Or></Where><GroupBy><FieldRefName="ProductTitle"/></GroupBy><OrderBy><FieldRefName="Priority"/><FieldRefName="Title"/></OrderBy>
The last example at this section:
caml = camlBuilder.Where() .LookupField("Category").Id().In([2, 3, 10]) .And() .DateField("ExpirationDate").LessThanOrEqualTo(CamlBuilder.CamlValues.Now) .OrderByDesc("ExpirationDate") .ToString()
As you see, the code is pretty clean and readable. The resulting CAML is much more awkward, especially if you imagine it in javascript strings dress, without indentation and highlighting...
<Where><And><In><FieldRefName="Category"LookupId="True"/><Values><ValueType="Integer">2</Value><ValueType="Integer">3</Value><ValueType="Integer">10</Value></Values></In><Leq><FieldRefName="ExpirationDate"/><ValueType="Date"><Now/></Value></Leq></And></Where><OrderBy><FieldRefName="ExpirationDate"Ascending="False"/></OrderBy>
CamlBuilder is not only readable and simple, but it also provides rich intellisense and inline documentation:
This will help to catch a bunch of errors when writing code, and surely prevent from typos and misunderstandings, so the benefits could be really magnificient!
Intellisense and inline docs are even better if you use CamlJs with TypeScript.
Any contributions are highly appreciated!