DoneJS StealJS jQuery++ FuncUnit DocumentJS
3.14.1
5.0.0 4.3.0 2.3.35
  • About
  • Guides
  • API Docs
  • Community
  • Contributing
  • Bitovi
    • Bitovi.com
    • Blog
    • Design
    • Development
    • Training
    • Open Source
    • About
    • Contact Us
  • About
  • Guides
  • API Docs
    • Observables
      • can-compute
      • can-define
      • can-define/list/list
      • can-define/map/map
      • can-define-stream
      • can-define-stream-kefir
      • can-event
      • can-event/async/async
      • can-event/batch/batch
      • can-event/lifecycle/lifecycle
      • can-kefir
      • can-list
      • can-map
      • can-map-backup
      • can-map-define
      • can-observation
      • can-observe
      • can-simple-map
      • can-simple-observable
      • can-stream
      • can-stream-kefir
    • Data Modeling
      • can-connect
      • can-connect-cloneable
      • can-connect-feathers
      • can-connect-ndjson
      • can-connect-signalr
      • can-fixture
      • can-fixture-socket
      • can-ndjson-stream
      • can-set
        • types
          • Set
          • Compares
          • Prop
        • properties
          • Algebra
          • Translate
          • props
    • Views
      • can-component
      • can-ejs
      • can-element
      • can-react-component
      • can-stache
      • can-stache/helpers/route
      • can-stache-bindings
      • can-stache-converters
      • can-view-autorender
      • can-view-callbacks
      • can-view-href
      • can-view-import
      • can-view-live
      • can-view-model
      • can-view-nodelist
      • can-view-parser
      • can-view-scope
      • can-view-target
      • react-view-model
      • react-view-model/component
      • steal-stache
    • Routing
      • can-deparam
      • can-param
      • can-route
      • can-route-pushstate
    • JS Utilities
      • can-assign
      • can-define-lazy-value
      • can-globals
      • can-key-tree
      • can-make-map
      • can-parse-uri
      • can-string
      • can-string-to-any
      • can-util
      • can-zone
      • can-zone-storage
    • DOM Utilities
      • can-ajax
      • can-attribute-encoder
      • can-control
      • can-dom-events
      • can-event-dom-enter
      • can-event-dom-radiochange
      • can-jquery
    • Data Validation
      • can-define-validate-validatejs
      • can-validate
      • can-validate-interface
      • can-validate-legacy
      • can-validate-validatejs
    • Typed Data
      • can-cid
      • can-construct
      • can-construct-super
      • can-namespace
      • can-reflect
      • can-reflect-promise
      • can-types
    • Polyfills
      • can-symbol
      • can-vdom
    • Core
    • Infrastructure
      • can-global
      • can-test-helpers
    • Ecosystem
    • Legacy
  • Community
  • Contributing
  • GitHub
  • Twitter
  • Chat
  • Forum
  • News
Bitovi

can-set

  • npm package badge
  • Star
  • Edit on GitHub

can-set is a utility for comparing sets that are represented by the parameters commonly passed to service requests.

Object

Once you've imported the can-set module into your project, use it to create a set.Algebra and then use that to compare and perform operations on sets.

import set from "can-set";

// create an algebra
const algebra = new set.Algebra(

    // specify the unique identifier on data
    set.props.id( "_id" ),

    // specify that completed can be true, false or undefined
    set.props.boolean( "completed" ),

    // specify properties that define pagination
    set.props.rangeInclusive( "start", "end" ),

    // specify the property that controls sorting
    set.props.sort( "orderBy" ),
);

// compare two sets
algebra.subset( { start: 2, end: 3 }, { start: 1, end: 4 } ); //-> true
algebra.difference( {}, { completed: true } ); //-> {completed: false}

// perform operations on sets
algebra.getSubset( { start: 2, end: 3 }, { start: 1, end: 4 },
    [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ] );

//-> [{id: 2},{id: 3}]

Use

A Set is a plain JavaScript object used to represent a set of data usually sent to the server to fetch a list of records. For example, a list of all completed todos might be represented by:

{complete: true}

This set might be passed to getList like:

Todo.getList({complete: true})

An Algebra is used to detail the behavior of these sets, often using already provided props comparators:

var todoAlgebra = new set.Algebra(
  set.props.boolean("complete"),
  set.props.id("_id")
);

Using an algebra, all sorts of special behaviors can be performed. For example, if we already loaded the incomplete todos ({complete: false}) and wanted to load all todos ({}), we could use a set difference to figure out how to load only the data that hasn't been loaded.

todoAlgebra.difference( {}, { complete: false } ); //-> {complete: true}

These algebra's are typically used internally by either can-connect or can-fixture to provide these special behaviors:

const cacheConnection = connect( [
    require( "can-connect/data/memory-cache/memory-cache" )
], {
    algebra: todoAlgebra
} );

const todoConnection = connect( [
    require( "can-connect/data/url/url" ),
    require( "can-connect/cache-requests/cache-requests" )
], {
    cacheConnection: cacheConnection,
    url: "/todos",
    algebra: todoAlgebra
} );
const todoStore = fixture.store( [
    { _id: 1, name: "Do the dishes", complete: true },
    { _id: 2, name: "Walk the dog", complete: false }
],
todoAlgebra );

fixture( "/todos/{_id}", todoStore );

The best way to think about can-set is that its a way to detail the behavior of your service layer so other utilities can benefit.

Solving Common Issues

Configuring the proper set.Algebra can be tricky. The best way to make sure you have things working is to create an algebra and make sure some of the basics work.

The most common problem is that your algebra isn't configured to know what instance data belongs in which set.

For example, {id: 1, name: "do dishes"} should belong to the set {sort: "name asc"}, but it doesn't:

const algebra = new set.Algebra();
algebra.has( { sort: "name asc" }, { id: 1, name: "do dishes" } ); //-> false

The fix is to either ignore sort like:

const algebra = new set.Algebra( {
    sort: function() {
        return true;
    }
} );
algebra.has( { sort: "name asc" }, { id: 1, name: "do dishes" } ); //-> false

Or even better, make sort actually able to understand sorting:

const algebra = new set.Algebra(
    set.props.sort( "sort" )
);
algebra.has( { sort: "name asc" }, { id: 1, name: "do dishes" } ); //-> true

Similarly, you can verify that getSubset works. The following, with a default algebra gives the wrong results:

const algebra = new set.Algebra();
algebra.getSubset(
    { offset: 1, limit: 2 },
    {},
    [
        { id: 1, name: "do dishes" },
        { id: 2, name: "mow lawn" },
        { id: 3, name: "trash" }
    ]
); //-> []

This is because it's looking for instance data where offset===1 and limit===2. Again, you can teach your algebra what to do with these properties like:

const algebra = new set.Algebra(
    set.props.offsetLimit( "offset", "limit" )
);
algebra.getSubset(
    { offset: 1, limit: 2 },
    {},
    [
        { id: 1, name: "do dishes" },
        { id: 2, name: "mow lawn" },
        { id: 3, name: "trash" }
    ]
); //-> [
//  {id: 2, name: "mow lawn"},
// {id: 3, name: "trash"}
// ]

CanJS is part of DoneJS. Created and maintained by the core DoneJS team and Bitovi. Currently 3.14.1.

On this page

Get help

  • Chat with us
  • File an issue
  • Ask questions
  • Read latest news