Git Product home page Git Product logo

checklist-model's Introduction

Bower NPM License

NPM

checklist-model

AngularJS directive for list of checkboxes

Why this is needed?

In Angular one checkbox <input type="checkbox" ng-model="..."> is linked with one model.
But in practice we usually want one model to store array of checked values from several checkboxes.
Checklist-model solves that task without additional code in controller.

Live demo

http://vitalets.github.io/checklist-model

Installation

Note: since version 1.0.0 you must install the angular library yourself as it is now a peerDependency

  1. Download package:
    • From npm npm install checklist-model
    • From bower bower install checklist-model
    • From latest release
  2. Include script to the HTML:
    <script src='checklist-model.js'></script>
  3. Add to app dependencies:
    var app = angular.module("app", ["checklist-model"]);

Usage

You should play with attributes of <input> tag:

Attribute Mandatory Description
checklist-model Yes Use instead of ng-model
checklist-value No What should be picked as array item
value No What should be picked as item, but unlike checklist-value, this does not evaluate as an angular expression, but rather a static value
ng-model No Every checkbok will span a new scope and define a variable named checked to hold its state. You can modify this name by using this attribute.
checklist-comparator No A custom comparator. If it starts with dot(.) then it will be an expression applied to the array item. Otherwise it should evaluate to a function as an angular expression. The function return true if the first two arguments are equal and false otherwise.
checklist-before-change No An angular expression evaluated each time before the checklist-model has changed. If it evaluates to 'false' then the model will not change anymore.
checklist-change No An angular expression evaluated each time the checklist-model has changed.
  • If you modify directly the value of the checklist-model, it is possible that the UI won't be updated. This is because this directive looks for the model in the parent, not in the current scope. Instead of doing checklistModelList = [] you should do checklistModelList.splice(0, checklistModelList.length) or wrap it in another object. Consequently, instead of doing checklistModelList = angular.copy(allValues) you should do checklistModelList.push.apply(checklistModelList, allValues). The idea is to use the same array and not replace it with a new one.
  • If you're using track by you must specify the same thing for checklist-value too. See #46.
  • If you're also using ngModel, please keep in mind that the state of the checkbok is initialized with the value from checklistModel, not with the one from ngModel. Afterwards the two will be kept in sync, but initially, these two can be conflicting, so only checklistModel is used. See the entire discussion at #104.

Examples

How to get support

Please keep in mind to also add a Plunkr or JSFiddle example. This will greatly help us in assisting you and you can use one of the existing examples and fork it.

Development

How to run tests

  1. Generate live demo index.html via grunt jade
  2. Run local http server grunt server
  3. Open in browser http://localhost:8000 to check that demo is accessible
  4. Open in browser http://localhost:8000/test and wait until all tests pass

How to add a new test case

  1. Create a new folder under docs/blocks named your-test.
  2. Create under that folder ctrl.js to describe the test Angular controller, view.html to describe the view part in HTML and test.js for the Angular scenario test. You can use an existing test as an example.
  3. Add a line like - items.push({id: 'your-test', text: 'Your test, ctrlName: 'CtrlTestName', testValue: 'selectedItems'}) to docs/index.jade
  4. Add a line like <script src="../docs/blocks/your-test/test.js"></script> to test\index.html
  5. Run grunt jade to generate index.html from docs/index.jade
  6. Run grunt server
  7. Access http://localhost:8000 for samples and http://localhost:8000/test for running the tests.

How to make a new release

  1. Change the version number in package.json, bower.json and checklist-model.nuspec (if not already changed - check the version number against the latest release in Github)
  2. Create a new release in github with the same name for tag and title as the version number (e.g. 1.0.0). Do not forget to include the changelog in the release description.
  3. Run npm publish to publish the new version to npm

License

MIT

checklist-model's People

Contributors

beradrian avatar caseyn avatar ccicpgreen avatar cschroedl-gov avatar dgasper avatar dotansimha avatar erickwilder avatar faheem-akhtar avatar guilleferrer avatar joostbaptist avatar marcopadillo avatar mathpere avatar sazo avatar tomchentw avatar vitalets avatar wjmazza avatar yiziz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

checklist-model's Issues

when checkAll, the checkboxs are not selected

When I click uncheckAll button, $scope.selectedItems is empty, but all the checkboxs are still selected. Is this because the id is not Number?
my data is like this:

$scope.data = [{
id: "234dfsdw43",
name: "name1"
},
{
id: "e4w54gr4",
name: "name2"
}]

JS:

$scope.checkAll = function() {
 $scope.selectedItems = $scope.data.map(function(item) { return item.id; });
};

$scope.uncheckAll = function() {
            $scope.selectedItems = [];
        };

HTML:

<div ng-repeat="item in data">
<input type="checkbox" checklist-model="selectedItems" checklist-value="item.id"> {{ item.name}}
 </div>
<button ng-click="checkAll()">check all</button>
<button ng-click="uncheckAll()">uncheck all</button>

Reset model problem

When I reset model array in this way
$scope.checklist = []

Checkboxes doesn't disappear.

issue with angular >= 1.2.15

Hi @vitalets,

I'm trying to use your directive with angular 1.2.15 but with no success. I checked that your demo site and your code jsfiddle are referencing to angular 1.0.8. Do you know if your directive is ready for use against angular 1.2.15? or I missing something else?

Thx in advance.

Allow checklist-value to handle strings instead of only scope values

Given:

<input type="checkbox" checklist-model="user.roles" checklist-value="someStringValue">
<input type="checkbox" checklist-model="user.roles" checklist-value="someStringValue2">

.. it should be able to handle these strings which aren't variable names. Right now, the following code returns undefined (L55):

// value added to list
var value = $parse(attrs.checklistValue)(scope.$parent);

The fix I had to put in place was this:

// value added to list
var value = $parse(attrs.checklistValue)(scope.$parent) || attrs.checklistValue;

watch (line 59) causes crash

If the list disappear, it is undefined. At this point, watch the line 59 will try to add a value to a variable undefined.

Should be corrected to get something like this:

 scope.$watch('checked', function(newValue, oldValue) {
 if (newValue === oldValue) {
      return;
 }
 var current = getter(scope.$parent);
 if (scope.$parent && current && value) {
      if (newValue === true) {
           setter(scope.$parent, add(current, value));
      } else {
           setter(scope.$parent, remove(current, value));
      }
 }"

$dirty is only updated when touch the last checkbox in the group

See below. If colors array is ['red', 'green', 'blue'], then ticking then un-ticking red or green doesn't affect $dirty state. Only when I tick and untick blue, then required error message will show up.

<form name="myForm">
  <div class="checkbox" ng-repeat="color in colors">
      <label>
        <input type="checkbox" name="color"
              checklist-model="formData['selectedColors']" 
              checklist-value="color" 
              ng-required="formData['selectedColors'].length == 0">
              {{color}}
      </label>
  </div>
  <p class="help-block error" 
    ng-show="myForm['color'].$error.required && myForm['color'].$dirty">
    This field is required.
  </p>
</form>

Checklist won't update if using track by $index inside ng-repeat

I've been using checklist-model to work with an array of check-boxes with each selected one can be deleted. Everything seems to work fine until I use it inside a ng-repeat.

The problem is, the deleted check-boxes still be there around when I add the track by $index along with the ng-repeat. If I remove that track by, it works fine (but in my real app I need that track by to work).

Here's a plnkr, http://plnkr.co/edit/5082nJfGwlOZaXYb184Z?p=preview

To see the problem, you can follow these steps.

1.Select any check-box you want
2/Delete those selected ones
3.Check the check all button to see,

Now look at the one with track by $index, it will leave some check-box unchecked. If you check it manually, it will have the old value added to the list. This is weird.

Missing required/minlength/maxlength functionality

There seems to be no way to make checklist-model require at least 1 checkbox to be selected.

I tried creating a checklist-required directive, but with no success as it doesn't use ngModel so I can't call ctrl.$setValidity.

Publish to npm

I'm managing all my dependencies through npm and would be very nice to find your repo.
Please add to npm registry.

Type property can't be changed.

This line is throwing the 'type property can't be changed' error.
if (tElement[0].tagName !== 'INPUT' || !tElement.attr('type', 'checkbox')) { throw 'checklist-model should be applied toinput[type="checkbox"].'; }
I'm using angular 1.2.8.

Model must be wrapped in an object

If the "checklist-model" attribute receives a flat list directly from the scope (like this: checklist-model="modelList") - it will be limited: if you clear all from the controller - the UI will not be updated (checks will still be checked).

I didn't test behaviour of select all.

In order to make it work, the model list must be wrapped in an object, like this:
<input type="checkbox" checklist-model="something.list" ...

and in the controller:
scope.something = {
list: [1,2,3]
}

TypeError when checklist-model is a function

The setter variable is undefined in the watch when the getter is a function. This leads to the following error message in the console:

TypeError: undefined is not a function
at Object.fn (checklist-model.js:69)
at Scope.$digest (angular.js:12251)
at Scope.$apply (angular.js:12516)
at HTMLTableRowElement. (angular.js:18626)
at angular.js:2780
at forEach (angular.js:330)
at HTMLTableRowElement.eventHandler (angular.js:2779)

How can I add an image to the check box and label?

I need to show the user a checkbox, an image, and title and allow them to select as many as they choose. ie. show the user various samples of granite and a title and ask them to pick all their favorite ones.

HTML5 compatibility

Hello i've found such a bug:

this work just fine:

and this crash the application

Publish to Bower and/or npm?

This project is exactly what I was looking for, but it would be great if I could add it to my package.json/bower.json rather than manually including it in my project :)

Checked values from list in list

hi,

I'm having trouble figuring out how to set the model to auto select when a model is loaded in, the models are like following:

$scope.group

{
    "Id": "08028136800d93f6",
    "Author": "John, Doe",
    "Name": "Test group",
    "Date": "2015-03-02T14:19:42",
    "ThumbnailUrl": null,
    "Keywords": [
        "test",
        "with keywords"
    ],
    "Videos": [
        {
            "Id": "09028136800d92b2",
            "Author": "John, Doe",
            "Title": "The Simpsons Movie trialer",
            "Genre": null,
            "version": "1.0",
            "Duration": 0,
            "Date": "2015-02-26T11:15:32",
            "ThumbnailUrl": null,
            "Keywords": [
                "testing",
                "input",
                "field",
                "simpsons",
                "movie",
                "1080p",
                "trailer"
            ],
            "ContentUrls": null,
            "Live": false,
            "ContentType": null,
            "State": 0,
        },
        {
            "Id": "09028136800d92d9",
            "Author": "John, Doe",
            "Title": "small lego movie to test",
            "Genre": null,
            "version": "1.0",
            "Duration": 0,
            "Date": "2015-02-26T14:47:56",
            "ThumbnailUrl": null,
            "Keywords": [
                "small",
                "lego",
                "movie",
                "test"
            ],
            "ContentUrls": null,
            "Live": false,
            "ContentType": null,
            "State": 0

        },
        {
            "Id": "09028136800d97b4",
            "Author": "John, Doe",
            "Title": "small.mp4",
            "Genre": null,
            "version": "1.0",
            "Duration": 0,
            "Date": "2015-03-02T09:27:18",
            "ThumbnailUrl": null,
            "Keywords": [],
            "ContentUrls": null,
            "Live": false,
            "ContentType": null,
            "State": 0
        }
    ]
}

and my $scope.videos is the same as the $scope.groups.Videos, except it contains all videos (and not only the one in the group)

The groups are created with the same form, and the $scope.group is then stringified when send, so the videos are correctly linked to $scope.group.Videos.

so, for some reason when the model is loaded again it won't check the ones in the repeat.
{{ group.Videos.length }} does return the correct amount of videos in the group, and when selecting a new one the count increases (so no reset)

form repeat:

<li class="collection-item" ng-repeat="video in filterdVideo = (videos |  filterStack : group.Videos:(query.length>0||showAll) | filter: query ) ">
    <p>
        <input type="checkbox" id="video_{{video.Id}}" checklist-model="group.Videos" checklist-value="video">
        <label for="video_{{video.Id}}">
            {{video.Title}}
        </label>
    </p>
</li>

EDIT:

don't know if important, but when doing some debugging is see that in the $scope.group.Videos contains of 3 objects (being the values in the DB / model) and 1 e (this being the one I checked)

Hard Return issue

For some reason, when I use the checklist model, everything is on one line. I have inserted
and

in everyplace available, but the best I can get is the labels on the next line after the checkboxes. Everything else is working great. Any ideas?

Current code is:

{{indType.name}}

Works only with subarray?

If I bind it to a simple array it is not working:
$scope.SelectedItems: []
It works only with:
$scope.anything= {
SelectedItems: []
};

Am I right?
The problem is with the function:
$scope.UnCheckAll = () => {
$scope.SelectedCertificateBlocks = [];
};
it updates the model but doesn't uncheck the checkboxes

Does this directive need a $destroy handler?

This directive works well for me if I comment out the $destroy handler (source), because these lines are wiping the model whenever the checklist directives are destroyed and appear to be modifying the parent scope.

I'm not sure I understand why we would need this functionality. Am I missing something?

Fails on minification

I am using codeSleeve minifcation for laravel4.
checklist-model fails on single checkbox select. SelectAll and unCheck all works normal.
Looks like checked=true is not being set in checklist-model on single checkbox selects.

Possible to Change ng-model Name for Each List?

I'm trying to use this on multiple checklists on one page. I need to save the selections of each list to localStorage. However, all of the checklist-model lists use the same ng-model name. So, it will only save all of the selections as one object.

Is there a way to change this for each list without changing checklist-model's core code?

Allow data-attributes

Normally you are allowed to write attribute directives as either checklist-model or data-checklist-model to be html5 compatible. $attrs normalizes that.
However, using data-checklist-model crashes chrome in your jsfiddle example and on my local I get a recursion problem.

Edit: the problem happens only with checklist-model, not with checklist-value.

checking all can make checkboxes disappear if using wrong method

Hi again,
In case you want to make a checkAll functionality look at this plunker.
http://plnkr.co/edit/6kld8n2x7gWKgFh81sen?p=preview

With the first method :
"$scope.user.roles = $scope.roles; "
All the checkboxes are selected but when one try to deselect a checkbox, it disappears from the list.
Why ? Because after $scope.user.roles = $scope.roles;
$scope.user.roles and $scope.roles become same object !
$scope.roles is not a clone of $scope.user.roles.
So when un-checking you actually delete the element from $scope.roles.

It seems evident thereafter but if someone is facing the same issue.. it can save him time.
Thanks for this directive

Enhance this directive to work with IE8

As it stands, this directive doesn't work with IE8 since the code is trying to set the type of the input to a checkbox (which isn't allowed) instead of evaluating it:

if (tElement[0].tagName !== 'INPUT' || !tElement.attr('type', 'checkbox')) {

should be changed to:

if (tElement[0].tagName !== 'INPUT' || tElement.attr('type') != 'checkbox') {

Plus, it just makes more sense to evaluate the type instead of setting it.

Feature Request - More uses to comparator

I want to use the checklist-value option to bind the entire object. But I do not want to write my own comparator function. It would be nice to use checklist-comparator to something like this:

            <label ng-repeat="rule in c.Rules">
                <input type="checkbox" name="checkBox[]" checklist-model="c.SelectedRule" checklist-value="rule" checklist-comparator="rule.Id"> {{rule.Name}}
            </label>

Isolate scope

Why not use isolate scope and pass in the model directly to the isolate scope? That way you wouldn't need the 'scope.$parent' workaround.

Checklist items are not binding to scope, when checked individually.

Following the example exactly as on the Demo site, when the checkboxes are clicked individually they do not bind to the scope. I have inspected it on the demo site with the angular inspector, on my own site (Angular 1.2.16), with in a Yo Angular app (Angular 1.2.6), with no luck. Am I incorrect to assume that the checkbox (checkbox-value) value is to bind to scope when clicked individually or does this require buttons with ng-click directives?

Remove excessive requirement input[type=checkbox]

Hi,

In order to use checklist-model with btn-checkbox from ui-bootstrap, I had to use a forked version of checklist-model by commenting these two lines:

if (tElement[0].tagName !== 'INPUT' || tAttrs.type !== 'checkbox') {
    throw 'checklist-model should be applied to `input[type="checkbox"]`.';
}

I can confirm this works like a charm. This requirement seems a little bit excessive. Could it be improved or removed?

Label on other line then ng-repeat

hi

I'm using materializecss, and there a checkbox has to have HTML like this:

<p>
    <input type="checkbox" id="test5" />
    <label for="test5">Red</label>
</p>

so the label is below the input, is it possible to use this module then?

<div ng-repeat="role in roles">
    <input type="checkbox" checklist-model="user.roles" checklist-value="role.id">
    <label>
        {{role.text}}
    </label>
</div>

wasn't sucesfull

Change the checked list from the controller

Hi,
Would it be possible to add the possibilty to :

  • uncheck elements from the controller

I have looked into the directive but it doesn't seem evident as you clone checklist-model and throw it away after.

Is it possible ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.