Extend angular-selection-model to handle select via mouse drag - angularjs

I am using the directive angular-selection-model for creating selectable lists.
EDIT:
I have a selectable list generated by the code below:
in codepen
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.2/angular.min.js"></script>
<script src="https://cdn.rawgit.com/jtrussell/angular-selection-model/master/dist/selection-model.js"></script>
<div ng-app="theApp" ng-controller="controller">
<ul>
<li ng-repeat="item in stuff track by $index" selection-model selection-model-mode="multiple-additive">
{{item.label}} - {{item.selected}}
</li>
</ul>
</div>
JS:
var myapp = angular.module('theApp', ['selectionModel']);
myapp.controller('controller', function ($scope) {
$scope.stuff = [
{selected: false, label: 'Scotchy scotch'},
{selected: true, label: 'Monacle'},
{selected: true, label: 'Curly mustache'},
{selected: false, label: 'Top hat'}
];
});
I would like to be able to select multiple objects by mouse dragging - as in this example. How do I enable this functionality?

Here is some example for angular drag selection
Sorry for answer in only link but you may understand good enough than my explanation.
1) http://jsfiddle.net/few5E/
2) https://github.com/willgm/ngSelectable
3) https://github.com/jonotron/angular-selectable

Related

How to make dynamic navigation for ul and li using angularjs?

I am trying to do dynamic navigation using ul and li. But i am not able to do for sub menu navigation, i am able to display parent menu only. I am using hashmap by using string and list as key value pairs.
Here's my code implemented
In angularjs script code:
$scope.listMap = [{'key':'Parent Menu', 'values':objectList}];
<div ng-repeat="(key,values) in listMap">
<ul>
<li>{{key}}
<div ng-repeat="value in values">
<ul>
<li>{{value.object.name}}</li>
<ul>
</div>
</li>
</ul>
</div>
It displays only parent menu but sub menu is not displaying, that i need another that if any of the parent menu that doesn't have sub menu i need to check that one in order to avoid running ul inside the main ul.
Can you please help me to proceed or share any examples for dynamic menus for navigation using angularjs.
Look at the code below. It is totally possible to do it. You just need to improve the structure of the data.
var app = angular.module('app',[]);
app.controller('controller', function($scope) {
$scope.listMap = [{
name: 'Home',
value: [{
name: 'File'
}, {
name: 'Items'
}]
}, {
name: 'Second Menu',
value: [{
name: 'Nothings'
}, {
name: 'Ooo LA LA'
}]
}, ];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="controller">
<div ng-repeat="item in listMap">
<ul>
<li>{{item.name}}
<div ng-repeat="value in item.value">
<ul>
<li>{{value.name}}</li>
<ul>
</div>
</li>
</ul>
</div>
</div>

Filter data on click function in AngularJS

I have data on some bikes in my HTML page. I have to filter that data via an on click function. I have used a filter in the text box area, but I want the same functionality via an on click function.
So how can I bind the filter with the click function?
http://jsfiddle.net/3G7Kd/114/
<div ng-app='app' class="filters_ct">
<ul class="nav" ng-controller="selectFilter">
<li ng-repeat="filter in filters" ng-click="select($index)" ng-class="{sel: $index == selected}">
<span class="filters_ct_status"></span>
{{filter.name}}
<ul class="subul" ng-if=filter.lists.length>
<li ng-repeat="list in filter.lists" ng-click=" $event.stopPropagation()">
<input type="checkbox"> {{list}}
</li>
</ul>
</li>
</ul>
<input type="text" ng-model="search">
<div ng-controller="listctrl">
<div class="list" ng-repeat="list in lists | filter:{brand:search}">
{{list.brand}}
{{list.year}}
</div>
</div>
</div>
Angular
var app = angular.module('app', []);
app.controller('selectFilter', function($scope) {
$scope.filters = [
{
"name": "brand",
'lists': ['yamaha','ducati','KTM','honda']
},
{
'name': "year",
'lists': [2012,2014,2015]
}
];
$scope.selected = 0;
$scope.select= function(index) {
if ($scope.selected === index)
$scope.selected = null
else
$scope.selected = index;
};
});
app.controller('listctrl', function($scope) {
$scope.lists = [
{
"brand": "ducati",
'year': 2012
},
{
'brand': "honda",
'year': 2014
},
{
'brand': "yamaha",
'year': 2015
},
{
'brand': "KTM",
'year': 2012
}
];
});
You already knew how to use the filter when given an object within the partial. I moved one of your controllers so that you have an outer and an inner controller.
<div ng-app='app'ng-controller="MainCtrl as mainCtrl">
<div ng-controller="listCtrl">
<!-- your filter object is now accessible here -->
</div>
</div>
I added a scope variable to the outer controller $scope.activeFilters (filling this you should be able to do on your own, see the plunker for one possible solution.
This object is now changed when clicking on the checkboxes. As $scope.activeFilters is now accessible from the inner controller we can pass it to the filter as before:
<div class="list" ng-repeat="list in lists | filter:activeFilters">
{{list.brand}}
{{list.year}}
</div>
Note that there are probably nicer solutions (using the checkbox with a model among other things).
Working plunker:
http://jsfiddle.net/ywfrbgoq/

Angularjs | how in directive change classes for siblings of clicked element?

I'm quite fresh with Angular, so sorry if my question looks trivial
I have few buttons, I create by ng-repeat. They have some bootstrap classes to make them nice, but if button is "active" gets additional class - active. The problem is only one button can be active, and I have 2 separate groups (containers with different class name) of buttons on page. They should work the same, but clicking on button on one groups should not affect the buttons in other group.
Could you, please help me write a directive, which will bind click event to button and remove 'active' class from all buttons in group and add it to clicked button only?
EDITED:
Here is a code in jsfiddle https://jsfiddle.net/996o7nk1/1/
HTML:
<!doctype html>
<html ng-app="confApp">
<head>
<title>Test</title>
<style>
.active {color: red;}
</style>
</head>
<body>
<div ng-controller="ProjectConfCtrl">
<div class="tans">
<button class="btn btn-default btn-cph" ng-repeat="tan in tans" ng-class="active: tan.active === true" data-tan-type-id="{{tan.id}}">{{tan.name}}</button>
</div>
<div class="langs">
<button class="btn btn-default btn-cph" data-ng-repeat="lang in langs">{{ lang.name }}</button>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="custom.js"></script>
</body>
</html>
JavaScript:
var app = angular.module("confApp", []);
app.controller('ProjectConfCtrl', [
'$scope', function($scope) {
$scope.tans = [
{
id: 1,
name: 'Auto',
active: true
}, {
id: 2,
name: 'Import',
active: false
}
];
$scope.langs = [
{
id: 1,
name: 'English',
active: true
}, {
id: 2,
name: 'Spanish',
active: false
}, {
id: 3,
name: 'German',
active: false
}
];
}
]);
For fiddle I just changed markup (removed html and head tag and added ng-app to div (it was in html)) but somehow in fiddle it throws an error.
I also added class, but it doesn't work also...
You can use ng-class together with a variable in the model, like in this fiddle:
https://jsfiddle.net/L5wm11s2/1/
Notice that I had to put the variables in the controller, not in the scope, and use the controller as to be able to access the variables from the view. That's because ng-repeat creates a child scope for each repeated element - a copy of the original scope, but separated from it. Because of that, if I did simply selectedTan = tan in ng-click, I'd end up setting the variable in the child scope. That means each button might consider itself selected, because it would have it's own selectedTan variable.

ng-repeat not working in script block

I need to call a js function when an ng-repeat template is created:
<div ng-repeat="item in items">
<input id="ip{{item.id}}">
<script>$(function () { $('#ip{{item.id}}').kendoDatePicker(); });</script>
</div>
The id is replaced as expected, but angular doesn't seem to work inside script tags.
That is correct, Angular will not evaluate expressions in script tags. You will need to use a directive that will initialize the Kendo plugin for each element.
The good news is Kendo already has a module for integrating with Angular, so you might as well just use that. Here is a plunk I put together showing it in a repeater.
<div ng-repeat="item in items">
<label for="{{item.id}}">{{item.id}}</label>
<div>
<input kendo-date-picker ng-model="item.value" />
</div>
</div>
Controller:
angular.module("demo", ['kendo.directives'])
.controller('DemoCtrl', ['$scope',
function($scope) {
$scope.items = [{
id: 'item1',
value: null
}, {
id: 'item2',
value: null
}, {
id: 'item3',
value: null
}, {
id: 'item4',
value: null
}];
}
]);

Removing Class from all children except clicked child on ng-click in Angular

I have a simple list item being parsed with ng-repeat:
<ul>
<li ng-repeat="item in items" class="commonClass" ng-class="{'on': on_var}" ng-click="on_var=!on_var">
{{item.name}}
<li>
</ul>
clicking on a list-item will add the class name 'on' as expected. but I want to remove all other 'on' classes as soon as you click on another list-item and only add it to the one clicked. I come from a jQuery background and I am new to angular. All I want to do is something like this:
$("li.commanClass").click(function(){
$("li.commonClass").removeClass('on');
$(this).addClass('on');
})
I want to know what is the "angular way" of achieving this result
jsfiddle
Thanks.
In angular you want to pass object references to child scopes as much as possible. This way you can use prototypical object inheritance that can branch down many levels.
Think of a scope as being a model. In the case of ng-repeat it creates a child scope for each element. So if the parent scope holds a model it will be passed as reference to the child scopes. Each of these child scopes will hold a reference to the parent scope model object.
Thus you can do:
<li ng-repeat="item in model.items"
ng-class="{'on': model.selected==item}"
ng-click="model.selected=item">{{ item.name }}</li>
Then in controller:
$scope.model = {
selected: null,
items = [
{name: "Apple"},
{name: "Banana"},
{name: "California"}
]
};
Try to avoid using functions as above answer does. These functions will get called many times and will add unnecessary extra overhead.
Valuable post to read: "Thinking in AngularJS" if I have a jQuery background?
DEMO
You can add a variable to your scope to maintain which item is selected, and a function on your scope that toggles the variable.
Controller:
app.controller('myCtrl', function($scope) {
$scope.items =
[
{name: "Apple"},
{name: "Banana"},
{name: "California"}
]
$scope.selectItem = function( item ) {
$scope.selectedItem = item;
};
})
HTML:
<div ng-app="myApp">
<ul ng-controller="myCtrl">
<li ng-repeat="item in items" class="commonClass" ng-class="{'on': selectedItem === item}" ng-click="selectItem(item)">
{{ item.name }}
</li>
</ul>
</div>
Fiddle coming at ya of jsparks answer:
http://jsfiddle.net/eHDTF/
See fiddle for code!
I think you should refer a directive for whole your project instead of controller.
<div class="nav-item">
<ul>
<li active-me="on">Item 1</li>
<li active-me="on">Item 2</li>
<li active-me="on">Item 3</li>
<li active-me="on">Item 4</li>
<li active-me="on">Item 5</li>
</ul>
</div>
Then create activeMe directive:
angular.module('app').directive('activeMe', function(){
return {
restrict: 'A',
scope: {
activeMe: '#'
},
link: function(scope, element, attrs) {
element.bind('click', function() {
if (scope.activeMe !== undefined && scope.activeMe.trim().length > 0) {
element.parent().children().removeClass(scope.activeMe);
element.addClass(scope.activeMe);
} else {
element.parent().children().removeClass('active');
element.addClass('active');
}
});
}
};
});

Resources