UNPKG

@bpa-solutions/camljs

Version:

Library for creating SharePoint CAML queries client-side. For JSOM, REST or SPServices.

295 lines (255 loc) 7.35 kB
## Installation Nuget: ``` PM> Install-Package CamlJs ``` Nuget TypeScript definitions: ``` PM> Install-Package camljs.TypeScript.DefinitelyTyped ``` Npm: ``` npm install camljs ``` Npm TypeScript definitions: ``` npm install @types/camljs ``` Also check out [CamlJs Console](https://github.com/andrei-markeev/camljs-console) - Chrome extension for testing queries with live preview against real lists. ## Usage In browser: ```html <script type="text/javascript" src="//unpkg.com/camljs"></script> <script> alert(new CamlBuilder().View().ToString()); </script> ``` In node: ```js var CamlBuilder = require('camljs'); console.log(new CamlBuilder().View().ToString()); ``` ES2015 modules: ```js import * as CamlBuilder from 'camljs'; console.log(new CamlBuilder().View().ToString()); ``` ## Basics Let's assume we need to fetch all Google-related emails from a SharePoint list where your company stores archived project emails. To generate the corresponding query using CamlJs, you could use following javascript code: ```js 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 the following CAML code: ```xml <Where> <Or> <Eq> <FieldRef Name="Email" /> <Value Type="Text">support@google.com</Value> </Eq> <Or> <Eq> <FieldRef Name="Email" /> <Value Type="Text">plus@google.com</Value> </Eq> <Or> <BeginsWith> <FieldRef Name="Title" /> <Value Type="Text">[Google]</Value> </BeginsWith> <Contains> <FieldRef Name="Content" /> <Value Type="Text">Google</Value> </Contains> </Or> </Or> </Or> </Where> ``` It is also possible to generate SP.CamlQuery object, just change `.ToString()` to `.ToCamlQuery()`. Another example: ```js var 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... ```xml <Where> <And> <In> <FieldRef Name="Category" LookupId="TRUE" /> <Values> <Value Type="Integer">2</Value> <Value Type="Integer">3</Value> <Value Type="Integer">10</Value> </Values> </In> <Leq> <FieldRef Name="ExpirationDate" /> <Value Type="Date"> <Now /> </Value> </Leq> </And> </Where><OrderBy> <FieldRef Name="ExpirationDate" Ascending="FALSE" /> </OrderBy> ``` ## Dynamic queries It's very easy to create dynamic queries with CamlJs by leveraging the `CamlBuilder.Expression()` construction. It's like a standalone part of query that can be later used in the final `new CamlBuilder.Where()` or `new CamlBuilder.View()`. ```js var categories = ["Category 1", "Category 2", "Category 3"]; var categoriesExpressions = categories.map(c => CamlBuilder.Expression().TextField("Category").EqualTo(c)); var caml = new CamlBuilder().Where() .Any(categoriesExpressions), .ToString(); ``` Result: ```xml <Where> <Or> <Eq> <FieldRef Name="Category" /> <Value Type="Text">Category 1</Value> </Eq> <Or> <Eq> <FieldRef Name="Category" /> <Value Type="Text">Category 2</Value> </Eq> <Eq> <FieldRef Name="Category" /> <Value Type="Text">Category 3</Value> </Eq> </Or> </Or> </Where> ``` While `.Any()` generates `<Or>` clauses, `.All()` will generate `<And>`. ## Elements support CamlJs supports all Query elements that are [described on MSDN](http://msdn.microsoft.com/en-us/library/ms467521.aspx). For example, seldom used Membership element: ```js var caml = camlBuilder.Where() .UserField("AssignedTo").EqualToCurrentUser() .Or() .UserField("AssignedTo").IsInCurrentUserGroups() .GroupBy("ProductTitle") .OrderBy("Priority").ThenBy("Title") .ToString(); ``` This code will generate following CAML: ```xml <Where> <Or> <Eq> <FieldRef Name="AssignedTo" /> <Value Type="Integer"> <UserID /> </Value> </Eq> <Membership Type="CurrentUserGroups"> <FieldRef Name="AssignedTo" /> </Membership> </Or> </Where> <GroupBy> <FieldRef Name="ProductTitle" /> </GroupBy> <OrderBy> <FieldRef Name="Priority" /> <FieldRef Name="Title" /> </OrderBy> ``` You can also create the upper-level View element as supported by SP.CamlQuery object. Scope attribute, ViewFields, Joins and ProjectedFields are supported in this case. Joining lists via CamlJs is very easy. Here's the example: ```js var query = new CamlBuilder() .View(["Title","Country","Population"]) .LeftJoin("Country","Country").Select("People","Population") .Query() .Where() .NumberField("Population").LessThan(10) .ToString(); ``` The resulting generated CAML query will be the following: ```xml <View> <ViewFields> <FieldRef Name="Title" /> <FieldRef Name="Country" /> <FieldRef Name="Population" /> </ViewFields> <Joins> <Join Type="LEFT" ListAlias="Country"> <Eq> <FieldRef Name="Country" RefType="ID" /> <FieldRef Name="ID" List="Country" /> </Eq> </Join> </Joins> <ProjectedFields> <Field ShowField="People" Type="Lookup" Name="Population" List="Country" /> </ProjectedFields> <Query> <Where> <Lt> <FieldRef Name="Population" /> <Value Type="Number">10</Value> </Lt> </Where> </Query> </View> ``` ## Modify existing queries Often you need to modify existing query (e.g. that comes from an existing list view), rather than generate a completely new one. This use case is also supported by CamlJs: - `CamlBuilder.FromXml(xml)` method will create a CamlBuilder object from existing CAML string - `ReplaceWhere` method then allows to replace <Where> clause with one generated by CamlJs - `ModifyWhere().AppendAnd()` will add new conditions to existing query using "And" operator - `ModifyWhere().AppendOr()` will add new conditions to existing query using "Or" operator Example: ```js var xml = new CamlBuilder().View().Query().Where() .UserField("Author").EqualToCurrentUser() .ToString(); var query = CamlBuilder.FromXml(xml) .ModifyWhere().AppendAnd() .LookupField("Country").ValueAsText().BeginsWith("G"); ``` Result: ```xml <View> <Query> <Where> <And> <Eq> <FieldRef Name="Author" LookupId="TRUE" /> <Value Type="Integer"> <UserID /> </Value> </Eq> <BeginsWith> <FieldRef Name="Country" /> <Value Type="Text">G</Value> </BeginsWith> </And> </Where> </Query> </View> ```