{"id":17193716,"url":"https://github.com/andrei-markeev/camljs","last_synced_at":"2025-04-09T12:07:07.331Z","repository":{"id":19682922,"uuid":"87644923","full_name":"andrei-markeev/camljs","owner":"andrei-markeev","description":"Library for creating SharePoint CAML queries client-side. For JSOM, REST or SPServices.","archived":false,"fork":false,"pushed_at":"2022-12-06T17:51:05.000Z","size":5765,"stargazers_count":76,"open_issues_count":13,"forks_count":22,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-04-13T17:05:28.961Z","etag":null,"topics":["sharepoint"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"ms-pl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrei-markeev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-08T15:45:11.000Z","updated_at":"2024-02-28T22:32:01.000Z","dependencies_parsed_at":"2023-01-13T20:31:20.243Z","dependency_job_id":null,"html_url":"https://github.com/andrei-markeev/camljs","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-markeev%2Fcamljs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-markeev%2Fcamljs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-markeev%2Fcamljs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-markeev%2Fcamljs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrei-markeev","download_url":"https://codeload.github.com/andrei-markeev/camljs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248036067,"owners_count":21037092,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["sharepoint"],"created_at":"2024-10-15T01:44:48.230Z","updated_at":"2025-04-09T12:07:07.313Z","avatar_url":"https://github.com/andrei-markeev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Installation\n\nNuget:\n```\nPM\u003e Install-Package CamlJs\n```\n\nNpm:\n```\nnpm install camljs\n```\n\nAlso check out [CamlJs Console](https://github.com/andrei-markeev/camljs-console) - Chrome extension for testing queries with live preview against real lists.\n\n## Usage\n\nIn browser:\n```html\n\u003cscript type=\"text/javascript\" src=\"//unpkg.com/camljs\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n    alert(new CamlBuilder().View().ToString());\n\u003c/script\u003e\n```\n\nIn Node.js:\n```js\nvar CamlBuilder = require('camljs');\nconsole.log(new CamlBuilder().View().ToString());\n```\n\nES2015 modules:\n```js\nimport * as CamlBuilder from 'camljs';\nconsole.log(new CamlBuilder().View().ToString());\n```\n\n## Basics\n\nLet'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:\n\n```js\nvar camlBuilder = new CamlBuilder();\n\nvar caml = camlBuilder.Where()\n    .TextField(\"Email\").EqualTo(\"support@google.com\")\n    .Or()\n    .TextField(\"Email\").EqualTo(\"plus@google.com\")\n    .Or()\n    .TextField(\"Title\").BeginsWith(\"[Google]\")\n    .Or()\n    .TextField(\"Content\").Contains(\"Google\")\n    .ToString();\n```\n\nThis will generate the following CAML code:\n\n```xml\n\u003cWhere\u003e\n  \u003cOr\u003e\n    \u003cEq\u003e\n      \u003cFieldRef Name=\"Email\" /\u003e\n      \u003cValue Type=\"Text\"\u003esupport@google.com\u003c/Value\u003e\n    \u003c/Eq\u003e\n    \u003cOr\u003e\n      \u003cEq\u003e\n        \u003cFieldRef Name=\"Email\" /\u003e\n        \u003cValue Type=\"Text\"\u003eplus@google.com\u003c/Value\u003e\n      \u003c/Eq\u003e\n      \u003cOr\u003e\n        \u003cBeginsWith\u003e\n          \u003cFieldRef Name=\"Title\" /\u003e\n          \u003cValue Type=\"Text\"\u003e[Google]\u003c/Value\u003e\n        \u003c/BeginsWith\u003e\n        \u003cContains\u003e\n          \u003cFieldRef Name=\"Content\" /\u003e\n          \u003cValue Type=\"Text\"\u003eGoogle\u003c/Value\u003e\n        \u003c/Contains\u003e\n      \u003c/Or\u003e\n    \u003c/Or\u003e\n  \u003c/Or\u003e\n\u003c/Where\u003e\n```\n\nIt is also possible to generate SP.CamlQuery object, just change `.ToString()` to `.ToCamlQuery()`.\n\nAnother example:\n```js\nvar caml = camlBuilder.Where()\n    .LookupField(\"Category\").Id().In([2, 3, 10])\n    .And()\n    .DateField(\"ExpirationDate\").LessThanOrEqualTo(CamlBuilder.CamlValues.Now)\n    .OrderByDesc(\"ExpirationDate\")\n    .ToString()\n```\nAs 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...\n```xml\n\u003cWhere\u003e\n  \u003cAnd\u003e\n    \u003cIn\u003e\n      \u003cFieldRef Name=\"Category\" LookupId=\"TRUE\" /\u003e\n      \u003cValues\u003e\n        \u003cValue Type=\"Integer\"\u003e2\u003c/Value\u003e\n        \u003cValue Type=\"Integer\"\u003e3\u003c/Value\u003e\n        \u003cValue Type=\"Integer\"\u003e10\u003c/Value\u003e\n      \u003c/Values\u003e\n    \u003c/In\u003e\n    \u003cLeq\u003e\n      \u003cFieldRef Name=\"ExpirationDate\" /\u003e\n      \u003cValue Type=\"Date\"\u003e\n        \u003cNow /\u003e\n      \u003c/Value\u003e\n    \u003c/Leq\u003e\n  \u003c/And\u003e\n\u003c/Where\u003e\u003cOrderBy\u003e\n  \u003cFieldRef Name=\"ExpirationDate\" Ascending=\"FALSE\" /\u003e\n\u003c/OrderBy\u003e\n```\n\n## Dynamic queries\n\nIt's very easy to create dynamic queries with CamlJs by leveraging the `CamlBuilder.Expression()` construction.\nIt's like a standalone part of query that can be later used in the final `new CamlBuilder.Where()` or `new CamlBuilder.View()`.\n\n```js\nvar categories = [\"Category 1\", \"Category 2\", \"Category 3\"];\n\nvar categoriesExpressions = categories.map(c =\u003e CamlBuilder.Expression().TextField(\"Category\").EqualTo(c));\n\nvar caml = new CamlBuilder().Where()\n    .Any(categoriesExpressions),\n    .ToString();\n```\nResult:\n```xml\n\u003cWhere\u003e\n    \u003cOr\u003e\n        \u003cEq\u003e\n            \u003cFieldRef Name=\"Category\" /\u003e\n            \u003cValue Type=\"Text\"\u003eCategory 1\u003c/Value\u003e\n        \u003c/Eq\u003e\n        \u003cOr\u003e\n            \u003cEq\u003e\n                \u003cFieldRef Name=\"Category\" /\u003e\n                \u003cValue Type=\"Text\"\u003eCategory 2\u003c/Value\u003e\n            \u003c/Eq\u003e\n            \u003cEq\u003e\n                \u003cFieldRef Name=\"Category\" /\u003e\n                \u003cValue Type=\"Text\"\u003eCategory 3\u003c/Value\u003e\n            \u003c/Eq\u003e\n        \u003c/Or\u003e\n    \u003c/Or\u003e\n\u003c/Where\u003e\n```\n\nWhile `.Any()` generates `\u003cOr\u003e` clauses, `.All()` will generate `\u003cAnd\u003e`.\n\n## Elements support\n\nCamlJs supports all Query elements that are [described on MSDN](http://msdn.microsoft.com/en-us/library/ms467521.aspx).\n\nFor example, seldom used Membership element:\n```js\nvar caml = camlBuilder.Where()\n    .UserField(\"AssignedTo\").EqualToCurrentUser()\n    .Or()\n    .UserField(\"AssignedTo\").IsInCurrentUserGroups()\n    .GroupBy(\"ProductTitle\")\n    .OrderBy(\"Priority\").ThenBy(\"Title\")\n    .ToString();\n```\nThis code will generate following CAML:\n\n```xml\n\u003cWhere\u003e\n  \u003cOr\u003e\n    \u003cEq\u003e\n      \u003cFieldRef Name=\"AssignedTo\" /\u003e\n      \u003cValue Type=\"Integer\"\u003e\n        \u003cUserID /\u003e\n      \u003c/Value\u003e\n    \u003c/Eq\u003e\n    \u003cMembership Type=\"CurrentUserGroups\"\u003e\n      \u003cFieldRef Name=\"AssignedTo\" /\u003e\n    \u003c/Membership\u003e\n  \u003c/Or\u003e\n\u003c/Where\u003e\n\u003cGroupBy\u003e\n  \u003cFieldRef Name=\"ProductTitle\" /\u003e\n\u003c/GroupBy\u003e\n\u003cOrderBy\u003e\n  \u003cFieldRef Name=\"Priority\" /\u003e\n  \u003cFieldRef Name=\"Title\" /\u003e\n\u003c/OrderBy\u003e\n```\n\n## Joins\n\nYou can also create the upper-level View element as supported by SP.CamlQuery object.\nScope attribute, ViewFields, Joins and ProjectedFields are supported in this case.\n\nJoining lists via CamlJs is very easy. Here's the example:\n\n```js\nvar query = new CamlBuilder()\n    .View([\"Title\",\"Country\",\"Population\"])\n    .LeftJoin(\"Country\",\"Country\").Select(\"People\",\"Population\")\n    .Query()\n    .Where()\n    .NumberField(\"Population\").LessThan(10)\n    .ToString();\n```\nThe resulting generated CAML query will be the following:\n```xml\n\u003cView\u003e\n    \u003cViewFields\u003e\n        \u003cFieldRef Name=\"Title\" /\u003e\n        \u003cFieldRef Name=\"Country\" /\u003e\n        \u003cFieldRef Name=\"Population\" /\u003e\n    \u003c/ViewFields\u003e\n    \u003cJoins\u003e\n        \u003cJoin Type=\"LEFT\" ListAlias=\"Country\"\u003e\n            \u003cEq\u003e\n                \u003cFieldRef Name=\"Country\" RefType=\"ID\" /\u003e\n                \u003cFieldRef Name=\"ID\" List=\"Country\" /\u003e\n            \u003c/Eq\u003e\n        \u003c/Join\u003e\n    \u003c/Joins\u003e\n    \u003cProjectedFields\u003e\n        \u003cField ShowField=\"People\" Type=\"Lookup\" Name=\"Population\" List=\"Country\" /\u003e\n    \u003c/ProjectedFields\u003e\n    \u003cQuery\u003e\n        \u003cWhere\u003e\n            \u003cLt\u003e\n                \u003cFieldRef Name=\"Population\" /\u003e\n                \u003cValue Type=\"Number\"\u003e10\u003c/Value\u003e\n            \u003c/Lt\u003e\n        \u003c/Where\u003e\n    \u003c/Query\u003e\n\u003c/View\u003e\n```\n\n## Modify existing queries\n\nOften you need to modify existing query (e.g. that comes from an existing list view), rather than generate a completely new one.\nThis use case is also supported by CamlJs:\n\n- `CamlBuilder.FromXml(xml)` method will create a CamlBuilder object from existing CAML string\n- `ReplaceWhere` method then allows to replace \u003cWhere\u003e clause with one generated by CamlJs\n- `ModifyWhere().AppendAnd()` will add new conditions to existing query using \"And\" operator\n- `ModifyWhere().AppendOr()` will add new conditions to existing query using \"Or\" operator\n\nExample:\n\n```js\nvar xml = new CamlBuilder().View().Query().Where()\n    .UserField(\"Author\").EqualToCurrentUser()\n    .ToString();\n\nvar query = CamlBuilder.FromXml(xml)\n    .ModifyWhere().AppendAnd()\n    .LookupField(\"Country\").ValueAsText().BeginsWith(\"G\");\n```\n\nResult:\n```xml\n\u003cView\u003e\n  \u003cQuery\u003e\n    \u003cWhere\u003e\n      \u003cAnd\u003e\n        \u003cEq\u003e\n          \u003cFieldRef Name=\"Author\" LookupId=\"TRUE\" /\u003e\n          \u003cValue Type=\"Integer\"\u003e\n            \u003cUserID /\u003e\n          \u003c/Value\u003e\n        \u003c/Eq\u003e\n        \u003cBeginsWith\u003e\n          \u003cFieldRef Name=\"Country\" /\u003e\n          \u003cValue Type=\"Text\"\u003eG\u003c/Value\u003e\n        \u003c/BeginsWith\u003e\n      \u003c/And\u003e\n    \u003c/Where\u003e\n  \u003c/Query\u003e\n\u003c/View\u003e\n```\n\n## More examples\n\nMore query examples can be found under [tests](https://github.com/andrei-markeev/camljs/tree/master/tests) folder.\n\nAlso, check out [examples](https://github.com/andrei-markeev/camljs/tree/master/examples) folder for usage examples in SP Addins and SPFx projects.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrei-markeev%2Fcamljs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrei-markeev%2Fcamljs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrei-markeev%2Fcamljs/lists"}