项目作者: andrei-markeev

项目描述 :
Library for creating SharePoint CAML queries client-side. For JSOM, REST or SPServices.
高级语言: TypeScript
项目地址: git://github.com/andrei-markeev/camljs.git
创建时间: 2017-04-08T15:45:11Z
项目社区:https://github.com/andrei-markeev/camljs

开源协议:Microsoft Public License

下载


Installation

Nuget:

  1. PM> Install-Package CamlJs

Npm:

  1. npm install camljs

Also check out CamlJs Console - Chrome extension for testing queries with live preview against real lists.

Usage

In browser:

  1. <script type="text/javascript" src="//unpkg.com/camljs"></script>
  2. <script>
  3. alert(new CamlBuilder().View().ToString());
  4. </script>

In Node.js:

  1. var CamlBuilder = require('camljs');
  2. console.log(new CamlBuilder().View().ToString());

ES2015 modules:

  1. import * as CamlBuilder from 'camljs';
  2. 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:

  1. var camlBuilder = new CamlBuilder();
  2. var caml = camlBuilder.Where()
  3. .TextField("Email").EqualTo("support@google.com")
  4. .Or()
  5. .TextField("Email").EqualTo("plus@google.com")
  6. .Or()
  7. .TextField("Title").BeginsWith("[Google]")
  8. .Or()
  9. .TextField("Content").Contains("Google")
  10. .ToString();

This will generate the following CAML code:

  1. <Where>
  2. <Or>
  3. <Eq>
  4. <FieldRef Name="Email" ></FieldRef>
  5. <Value Type="Text">support@google.com</Value>
  6. </Eq>
  7. <Or>
  8. <Eq>
  9. <FieldRef Name="Email" ></FieldRef>
  10. <Value Type="Text">plus@google.com</Value>
  11. </Eq>
  12. <Or>
  13. <BeginsWith>
  14. <FieldRef Name="Title" ></FieldRef>
  15. <Value Type="Text">[Google]</Value>
  16. </BeginsWith>
  17. <Contains>
  18. <FieldRef Name="Content" ></FieldRef>
  19. <Value Type="Text">Google</Value>
  20. </Contains>
  21. </Or>
  22. </Or>
  23. </Or>
  24. </Where>

It is also possible to generate SP.CamlQuery object, just change .ToString() to .ToCamlQuery().

Another example:

  1. var caml = camlBuilder.Where()
  2. .LookupField("Category").Id().In([2, 3, 10])
  3. .And()
  4. .DateField("ExpirationDate").LessThanOrEqualTo(CamlBuilder.CamlValues.Now)
  5. .OrderByDesc("ExpirationDate")
  6. .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…

  1. <Where>
  2. <And>
  3. <In>
  4. <FieldRef Name="Category" LookupId="TRUE" ></FieldRef>
  5. <Values>
  6. <Value Type="Integer">2</Value>
  7. <Value Type="Integer">3</Value>
  8. <Value Type="Integer">10</Value>
  9. </Values>
  10. </In>
  11. <Leq>
  12. <FieldRef Name="ExpirationDate" ></FieldRef>
  13. <Value Type="Date">
  14. <Now ></Now>
  15. </Value>
  16. </Leq>
  17. </And>
  18. </Where><OrderBy>
  19. <FieldRef Name="ExpirationDate" Ascending="FALSE" ></FieldRef>
  20. </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().

  1. var categories = ["Category 1", "Category 2", "Category 3"];
  2. var categoriesExpressions = categories.map(c => CamlBuilder.Expression().TextField("Category").EqualTo(c));
  3. var caml = new CamlBuilder().Where()
  4. .Any(categoriesExpressions),
  5. .ToString();

Result:

  1. <Where>
  2. <Or>
  3. <Eq>
  4. <FieldRef Name="Category" ></FieldRef>
  5. <Value Type="Text">Category 1</Value>
  6. </Eq>
  7. <Or>
  8. <Eq>
  9. <FieldRef Name="Category" ></FieldRef>
  10. <Value Type="Text">Category 2</Value>
  11. </Eq>
  12. <Eq>
  13. <FieldRef Name="Category" ></FieldRef>
  14. <Value Type="Text">Category 3</Value>
  15. </Eq>
  16. </Or>
  17. </Or>
  18. </Where>

While .Any() generates <Or> clauses, .All() will generate <And>.

Elements support

CamlJs supports all Query elements that are described on MSDN.

For example, seldom used Membership element:

  1. var caml = camlBuilder.Where()
  2. .UserField("AssignedTo").EqualToCurrentUser()
  3. .Or()
  4. .UserField("AssignedTo").IsInCurrentUserGroups()
  5. .GroupBy("ProductTitle")
  6. .OrderBy("Priority").ThenBy("Title")
  7. .ToString();

This code will generate following CAML:

  1. <Where>
  2. <Or>
  3. <Eq>
  4. <FieldRef Name="AssignedTo" ></FieldRef>
  5. <Value Type="Integer">
  6. <UserID ></UserID>
  7. </Value>
  8. </Eq>
  9. <Membership Type="CurrentUserGroups">
  10. <FieldRef Name="AssignedTo" ></FieldRef>
  11. </Membership>
  12. </Or>
  13. </Where>
  14. <GroupBy>
  15. <FieldRef Name="ProductTitle" ></FieldRef>
  16. </GroupBy>
  17. <OrderBy>
  18. <FieldRef Name="Priority" ></FieldRef>
  19. <FieldRef Name="Title" ></FieldRef>
  20. </OrderBy>

Joins

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:

  1. var query = new CamlBuilder()
  2. .View(["Title","Country","Population"])
  3. .LeftJoin("Country","Country").Select("People","Population")
  4. .Query()
  5. .Where()
  6. .NumberField("Population").LessThan(10)
  7. .ToString();

The resulting generated CAML query will be the following:

  1. <View>
  2. <ViewFields>
  3. <FieldRef Name="Title" ></FieldRef>
  4. <FieldRef Name="Country" ></FieldRef>
  5. <FieldRef Name="Population" ></FieldRef>
  6. </ViewFields>
  7. <Joins>
  8. <Join Type="LEFT" ListAlias="Country">
  9. <Eq>
  10. <FieldRef Name="Country" RefType="ID" ></FieldRef>
  11. <FieldRef Name="ID" List="Country" ></FieldRef>
  12. </Eq>
  13. </Join>
  14. </Joins>
  15. <ProjectedFields>
  16. <Field ShowField="People" Type="Lookup" Name="Population" List="Country" ></Field>
  17. </ProjectedFields>
  18. <Query>
  19. <Where>
  20. <Lt>
  21. <FieldRef Name="Population" ></FieldRef>
  22. <Value Type="Number">10</Value>
  23. </Lt>
  24. </Where>
  25. </Query>
  26. </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 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:

  1. var xml = new CamlBuilder().View().Query().Where()
  2. .UserField("Author").EqualToCurrentUser()
  3. .ToString();
  4. var query = CamlBuilder.FromXml(xml)
  5. .ModifyWhere().AppendAnd()
  6. .LookupField("Country").ValueAsText().BeginsWith("G");

Result:

  1. <View>
  2. <Query>
  3. <Where>
  4. <And>
  5. <Eq>
  6. <FieldRef Name="Author" LookupId="TRUE" ></FieldRef>
  7. <Value Type="Integer">
  8. <UserID ></UserID>
  9. </Value>
  10. </Eq>
  11. <BeginsWith>
  12. <FieldRef Name="Country" ></FieldRef>
  13. <Value Type="Text">G</Value>
  14. </BeginsWith>
  15. </And>
  16. </Where>
  17. </Query>
  18. </View>

More examples

More query examples can be found under tests folder.

Also, check out examples folder for usage examples in SP Addins and SPFx projects.