I have the following JSON object:
[
{
"districtId": 1,
"districtAddress": "108 N MAIN ST",
"offices": [
{
"Id": 11,
"name": "test",
"City": "ATMORE"
},
{
"Id": 22,
"name": "test",
"City": "ATMORE"
}
]
},
{
"districtId": 2,
"districtAddress": "108 N MAIN ST",
"offices": [
{
"Id": 33,
"name": "test",
"City": "ATMORE"
},
{
"Id": 44,
"name": "test",
"City": "ATMORE"
}
]
},
{
"districtId": 3,
"districtAddress": "108 N MAIN ST",
"offices": [
{
"Id": 55,
"name": "test",
"City": "ATMORE"
}
]
}
]
I want to show this data using md-virtual-repeat directive. First level repeater works when I use this directive.
But when I try to render the inner data using the same directive - it doesn't work as expected. How can use md-virtual-repeat for the nested repeater (I want to get rid of ng-repeat on md-list-item element)?
Here is my code:
angular
.module('MyApp',['ngMaterial'])
.controller('AppCtrl', function($scope) {
var self = this;
self.items = [];
for (var i = 0; i < 1000; i++) {
var item = {
nbr: i,
items: []
};
for(var m = 0; m < 10; m++) {
item.items.push({
nbr: m,
checked: true
});
}
self.items.push(item);
}
});
.virtualRepeatStoreList .vertical-container {
height: 500px;
width: 100%;
}
.virtualRepeatStoreList .repeated-item {
border-bottom: 1px solid #ddd;
box-sizing: border-box;;
height: 40px;
padding-top: 10px;
}
.virtualRepeatStoreList md-content {
margin: 16px;
}
.virtualRepeatStoreList .md-virtual-repeat-container .md-virtual-repeat-offsetter div {
padding-left: 5px;
}
<link rel="stylesheet prefetch" href="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.0/angular-material.css">
<link rel="stylesheet prefetch" href="https://material.angularjs.org/1.1.0/docs.css">
<div ng-controller="AppCtrl as ctrl" class="content virtualRepeatStoreList" ng-app="MyApp">
<md-virtual-repeat-container class="vertical-container" style="height:550px">
<div md-virtual-repeat="item in ctrl.items">
<md-card flex="">
<md-card-title>
<md-card-title-text>
<span class="md-display-2">{{ item.nbr }}</span>
</md-card-title-text>
</md-card-title>
<md-list style="overflow:auto;height:auto;" flex ng-cloak layout="column">
<md-divider></md-divider>
<md-list-item layout="row" class="noright">
<md-subheader flex>Item</md-subheader>
</md-list-item>
<md-list-item ng-repeat="it in item.items" style="max-height:40px;overflow:hidden;" class="noright">
<p>{{ it.nbr }}</p>
<md-checkbox class="md-secondary" ng-model="it.checked"></md-checkbox>
</md-list-item>
</md-list>
</md-card>
</div>
</md-virtual-repeat-container>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-aria.min.js"></script>
<script src="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.0/angular-material.js"></script>
You need to wrap each nested md-virtual-repeat with md-virtual-repeat-container like:
angular
.module('MyApp',['ngMaterial'])
.controller('AppCtrl', function($scope) {
var self = this;
self.items = [];
for (var i = 0; i < 1000; i++) {
var item = {
nbr: i,
items: []
};
for(var m = 0; m < 10; m++) {
item.items.push({
nbr: m,
checked: true
});
}
self.items.push(item);
}
});
.virtualRepeatStoreList .vertical-container {
height: 500px;
width: 100%;
}
.virtualRepeatStoreList .repeated-item {
border-bottom: 1px solid #ddd;
box-sizing: border-box;;
height: 40px;
padding-top: 10px;
}
.virtualRepeatStoreList md-content {
margin: 16px;
}
.virtualRepeatStoreList .md-virtual-repeat-container .md-virtual-repeat-offsetter div {
padding-left: 5px;
}
md-list-item.md-no-proxy.md-no-padding {
padding: 0;
}
<link rel="stylesheet prefetch" href="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.0/angular-material.css">
<link rel="stylesheet prefetch" href="https://material.angularjs.org/1.1.0/docs.css">
<div ng-controller="AppCtrl as ctrl" class="content virtualRepeatStoreList" ng-app="MyApp">
<md-virtual-repeat-container class="vertical-container" style="height:550px">
<div md-virtual-repeat="item in ctrl.items">
<md-card flex="">
<md-card-title>
<md-card-title-text>
<span class="md-display-2">{{ item.nbr }}</span>
</md-card-title-text>
</md-card-title>
<md-list style="overflow:auto;height:auto;" flex ng-cloak layout="column">
<md-divider></md-divider>
<md-list-item layout="row" class="noright md-no-padding">
<md-subheader flex>Item</md-subheader>
</md-list-item>
<md-virtual-repeat-container class="vertical-container" style="height:125px">
<md-list-item md-virtual-repeat="it in item.items" style="max-height:40px;overflow:hidden;" class="noright">
<p>{{ it.nbr }}</p>
<md-checkbox class="md-secondary" ng-model="it.checked"></md-checkbox>
</md-list-item>
</md-virtual-repeat-container>
</md-list>
</md-card>
</div>
</md-virtual-repeat-container>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-aria.min.js"></script>
<script src="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.0/angular-material.js"></script>
Related
Look in this fiddle https://jsfiddle.net/Lj0swckj/3/
I have created directive for sortable
For parent divs sortable working fine
I want same thing for childs also with containment as its parent
In the given example child1, child2, child3 can swap positions and containment will be parent1.
I tried a lot but can't find anything
Note: There can also children for a child1, child2...
(Here In this example i have added data for two levels but it can be upto four levels)
So I want a solution where sortable can work for such kind of recursive templates.
Any Help would be appreciated.
angular.module("myApp", []).
controller("myController", ['$scope', function($scope) {
$scope.fields = [{
"name": "parent1",
"level": 1,
"children": [{
"name": "child1",
"level": 2
}, {
"name": "child2",
"level": 2
}, {
"name": "child3",
"level": 2
}]
}, {
"name": "parent2",
"level": 1
}, {
"name": "parent3",
"level": 1
}];
$scope.draggableItemsOption = {
"moverElement": ".moverBtn",
"containment": ".draggable-field"
}
}]).directive("myDragDrop", ['$timeout', function ($timeout) {
return {
restrict:'A',
scope: {
myDragDrop:"="
},
link: function ($scope, element, attrs) {
var options = $scope.myDragDrop;
var $container = element;
var sortableOptions = {
/* handle: options.moverElement, */
containment: options.containment,
delay: 0
};
if($container.sortable){
$container.sortable(sortableOptions);
}
}
}
}]);
.element {
border: 1px solid #333;
padding: 10px 10px;
position: relative;
}
.element-class {
margin-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<div class="draggable-field" my-drag-drop="draggableItemsOption">
<div ng-repeat="data in fields">
<div class="element" ng-class="{'element-class': data.level > 1}">
{{data.name}}
<div ng-repeat="childData in data.children">
<div class="element" ng-class="{'element-class': data.level > 1}">
{{childData.name}}
</div>
</div>
</div>
</div>
</div>
</div>
Huh ! Finally Got a solution.
Actually it is pretty simple
Here look at this fiddle https://jsfiddle.net/Lj0swckj/6/
What I did is created child elems
angular.module("myApp", []).
controller("myController", ['$scope', function($scope) {
$scope.fields = [{
"name": "parent1",
"level": 1,
"children": [{
"name": "child1",
"level": 2
}, {
"name": "child2",
"level": 2
}, {
"name": "child3",
"level": 2,
"children": [{
"name": "grandChild1",
"level": 3
}, {
"name": "grandChild2",
"level": 3
}]
}]
}, {
"name": "parent2",
"level": 1,
"children": [{
"name": "child4",
"level":2
}]
}, {
"name": "parent3",
"level": 1
}];
$scope.draggableItemsOption = {
"moverElement": ".moverBtn",
"containment": ".draggable-field"
}
$scope.childDraggableItemsOption = {
"containment": "parent"
}
}]).directive("myDragDrop", ['$timeout', function ($timeout) {
return {
restrict:'A',
scope: {
myDragDrop:"="
},
link: function ($scope, element, attrs) {
var options = $scope.myDragDrop;
var $container = element;
var sortableOptions = {
/* handle: options.moverElement, */
containment: options.containment,
delay: 0
};
if($container.sortable){
$container.sortable(sortableOptions);
}
}
}
}]);
.element {
border: 1px solid #333;
padding: 10px 10px;
position: relative;
}
.element-class {
margin-left: 20px;
}
.moverBtn {
position: absolute;
top: 2px;
right: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-autocomplete/1.0.7/jquery.auto-complete.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<script type="text/ng-template" id="tree_item_renderer.html">
<div class="child-draggable-field" my-drag-drop="childDraggableItemsOption">
<div ng-repeat="data in data.children" ng-class="{'element-class': data.level > 1}">
<div class="element"> {{data.name}} ------ {{$parent.$parent.data.children.length}}</div>
<div ng-include="'tree_item_renderer.html'">
</div>
</div>
</div>
</script>
<div class="draggable-field" my-drag-drop="draggableItemsOption">
<div ng-repeat="data in fields">
<div class="element" ng-class="{'element-class': data.level > 1}">
{{data.name}}
<div ng-include="'tree_item_renderer.html'">
</div>
</div>
</div>
</div>
</div>
I have a problem when clicking on images the mp3 plays, but when i make a query on ng-repeat it doesn't work anymore.
It's from the getElementsByClassName index, but i need to fix it.
Is there any good way to make it work with angular, like ng-audio ?
<html>
<heaD>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-audio/1.7.2/angular.audio.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('controller', ['$scope', function($scope) {
$scope.playit = function(id){
var audio = document.getElementsByClassName("audio")[id];
audio.play();
}
$scope.data=[{
id: 0,
categorie: ['Rectorat', 'General', 'Secretariate'],
denumire: 'Rectorat',
imagine: '1-RECTORAT.jpg',
linkAudio: "audio/rectorat-notgood.mp3",
descriereText: 'Bd. Mamaia nr. 124, etaj 1...',
linkHarta: ''
},
{
id: 1,
categorie: ['Juridic', 'General', 'Secretariate'],
denumire: 'Juridic',
imagine: '1-RECTORAT.jpg',
linkAudio: "audio/rectorat-notgood.mp3",
descriereText: 'Bd. Mamaia nr. 124, etaj 1...',
linkHarta: ''
},
{
id: 2,
categorie: ['Facultatea de Matematica si Informatica', 'Secretariate'],
denumire: 'Secretariat Facultatea de Matematica si Informatica',
imagine: '1-RECTORAT.jpg',
linkAudio: "audio/rectorat-notgood.mp3",
descriereText: 'indicatii',
linkHarta: ''
},
{
id: 3,
categorie: ['Facultatea de Matematica si Informatica', 'Secretariate'],
denumire: 'Secretariat Facultatea de Matematica si Informatica',
imagine: '1-RECTORAT.jpg',
linkAudio: "audio/test.mp3",
descriereText: 'indicatii',
linkHarta: ''
}];
}]);
</script>
<style>
.col-xs-12 {
padding-bottom:10px;
}
.col-sm-6 {
padding-bottom:10px;
}
.centrat {
margin: auto;
}
</style>
</heaD>
<body ng-app="myApp" data-ng-cloak data-ng-controller="controller">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<img src="img/logo-site.jpg" class="centrat img-responsive"></span>
</div>
</div>
<div class="row">
<div class="col-lg-12" style="padding-bottom: 20px;">
<input type="textarea" class="form-control" ng-model="query.categorie" placeholder="Cautare" style="width: 100%; height: 100px;">
</div>
</div>
<div class="row" >
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-2" ng-repeat="locatie in data | filter:query" >
<div >
<img class="img-responsive" ng-src="img/{{locatie.imagine}}" style="margin: auto;" ng-click="playit(locatie.id)">
<audio class="audio" ng-src="{{locatie.linkAudio}}" ></audio>
</img>
<p style="font-size: 10px;">{{locatie.denumire}} |
{{locatie.descriereText}}</p>
</div>
</div>
</div>
</div>
</body>
</html>
I fix your code, it's work for me
<!DOCTYPE html>
<html>
<heaD>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-audio/1.7.2/angular.audio.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('controller', ['$scope', '$sce', function($scope, $sce) {
var arrayPL = document.getElementsByClassName("audio");
$scope.playit = function(id){
var audio = arrayPL[id];
if (audio.paused === false) {
audio.pause();
} else {
audio.play();
}
}
$scope.data=[{
id: 0,
categorie: ['Rectorat', 'General', 'Secretariate'],
denumire: 'Rectorat',
imagine: 'https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png',
linkAudio: "http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
descriereText: 'Bd. Mamaia nr. 124, etaj 1...',
linkHarta: ''
},
{
id: 1,
categorie: ['Juridic', 'General', 'Secretariate'],
denumire: 'Juridic',
imagine: 'https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png',
linkAudio: "http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
descriereText: 'Bd. Mamaia nr. 124, etaj 1...',
linkHarta: ''
},
{
id: 2,
categorie: ['Facultatea de Matematica si Informatica', 'Secretariate'],
denumire: 'Secretariat Facultatea de Matematica si Informatica',
imagine: 'https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png',
linkAudio: "http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
descriereText: 'indicatii',
linkHarta: ''
},
{
id: 3,
categorie: ['Facultatea de Matematica si Informatica', 'Secretariate'],
denumire: 'Secretariat Facultatea de Matematica si Informatica',
imagine: 'https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png',
linkAudio: "http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
descriereText: 'indicatii',
linkHarta: ''
}];
$scope.trustURL = function (url) {
return $sce.trustAsResourceUrl(url);
}
}]);
</script>
<style>
.col-xs-12 {
padding-bottom:10px;
}
.col-sm-6 {
padding-bottom:10px;
}
.centrat {
margin: auto;
}
.img-responsive {
width: 100px;
}
</style>
</heaD>
<body ng-app="myApp" data-ng-cloak data-ng-controller="controller">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<img src="img/logo-site.jpg" class="centrat img-responsive">
</div>
</div>
<div class="row">
<div class="col-lg-12" style="padding-bottom: 20px;">
<input type="textarea" class="form-control" ng-model="query.categorie" placeholder="Cautare" style="width: 100%; height: 100px;">
</div>
</div>
<div class="row" >
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-2" ng-repeat="locatie in data | filter:query" >
<div >
<img class="img-responsive" ng-src="{{trustURL(locatie.imagine)}}" ng-click="playit(locatie.id)">
<audio class="audio" ng-src="{{trustURL(locatie.linkAudio)}}" ></audio>
<p style="font-size: 10px;">{{locatie.denumire}} |
{{locatie.descriereText}}</p>
</div>
</div>
</div>
</div>
</body>
</html>
Notes:
You need to use $sce.trustAsResourceUrl, then you're able use the imagine and linkAudio;
To filter the audios by their categories, you don't need to do a custom filter, you can simply do a deep array filter inside it, like this:
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-2" ng-repeat="locatie in data | filter: { categories: search }">
Here's a snippet working:
(function() {
"use strict";
angular.module('app', [])
.controller('mainCtrl', function($scope, $sce) {
var audioItems = document.getElementsByClassName("audio");
$scope.play = function(locatie) {
var audio = audioItems[locatie.id];
if (!audio.paused) {
audio.pause();
} else {
audio.play();
}
}
$scope.data = [
{
"id":0,
"categories":[
"Rectorat",
"General",
"Secretariate"
],
"denumire":"Rectorat",
"imagine":"https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png",
"linkAudio":"http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
"descriereText":"Bd. Mamaia nr. 124, etaj 1...",
"linkHarta":""
},
{
"id":1,
"categories":[
"Juridic",
"General",
"Secretariate"
],
"denumire":"Juridic",
"imagine":"https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png",
"linkAudio":"http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
"descriereText":"Bd. Mamaia nr. 124, etaj 1...",
"linkHarta":""
},
{
"id":2,
"categories":[
"Facultatea de Matematica si Informatica",
"Secretariate"
],
"denumire":"Secretariat Facultatea de Matematica si Informatica",
"imagine":"https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png",
"linkAudio":"http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
"descriereText":"indicatii",
"linkHarta":""
},
{
"id":3,
"categories":[
"Facultatea de Matematica si Informatica",
"Secretariate"
],
"denumire":"Secretariat Facultatea de Matematica si Informatica",
"imagine":"https://cdn2.iconfinder.com/data/icons/web-interface-icons/66/Img-512.png",
"linkAudio":"http://muz-tv.ru/audio/a/3/a38b663b5b2a98220266a56529ae75de.mp3?id=843",
"descriereText":"indicatii",
"linkHarta":""
}
];
// You can use map to set all your url items to be trusted, as follows:
$scope.data.map(function(value) {
value.imagine = $sce.trustAsResourceUrl(value.imagine);
value.linkAudio = $sce.trustAsResourceUrl(value.linkAudio);
})
});
})();
.col-xs-12 {
padding-bottom: 10px;
}
.col-sm-6 {
padding-bottom: 10px;
}
.centrat {
margin: auto;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body ng-cloak ng-controller="mainCtrl">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<img src="http://a5.mzstatic.com/us/r30/Purple/v4/8d/42/72/8d427222-6310-a43f-5d79-13c3a24c0ce5/icon128-2x.png" class="centrat img-responsive">
</div>
</div>
<div class="row">
<div class="col-lg-12" style="padding-bottom: 20px;">
<input type="textarea" class="form-control" ng-model="search" placeholder="Filter" style="width: 100%; height: 100px;">
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-2" ng-repeat="locatie in data | filter: { categories: search }">
<div>
<img class="img-responsive" ng-src="{{locatie.imagine}}" ng-click="play(locatie)">
<audio class="audio" ng-src="{{locatie.linkAudio}}"></audio>
<p style="font-size: 10px;" ng-bind="locatie.denumire + ' | ' + locatie.descriereText">
</div>
</div>
</div>
</div>
</body>
</html>
I was having a problem getting the simple demo to work found here.
I'm getting the two lists to show up, however I am unable to drag and drop items. The demo is very simple, just an html file, javascript file and css file.
Here's my index.html file:
<!DOCTYPE html>
<html ng-app="demo">
<head lang="en">
<meta charset="utf-8">
<title>Drag & Drop Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="bower_components/angular-drag-and-drop-lists/angular-drag-and-drop-lists.min.js"></script>
<script src="Scripts/my-app.js"></script>
<link href="Content/my-styling.css" rel="stylesheet" />
</head>
<body class="simpleDemo" ng-controller="SimpleDemoController">
<ul dnd-list="list">
<li ng-repeat="item in models.lists.A"
dnd-draggable="item"
dnd-moved="models.lists.A.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}">
{{item.label}}
</li>
</ul>
<ul dnd-list="list">
<li ng-repeat="item in models.lists.B"
dnd-draggable="item"
dnd-moved="models.lists.B.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}">
{{item.label}}
</li>
</ul>
</body>
</html>
Here's my js file:
angular.module("demo", []).controller("SimpleDemoController", function ($scope) {
$scope.models = {
selected: null,
lists: { "A": [], "B": [] }
};
// Generate initial model
for (var i = 1; i <= 3; ++i) {
$scope.models.lists.A.push({ label: "Item A" + i });
$scope.models.lists.B.push({ label: "Item B" + i });
}
// Model to JSON for demo purpose
$scope.$watch('models', function (model) {
$scope.modelAsJson = angular.toJson(model, true);
}, true);
});
And here's my css file:
.simpleDemo ul[dnd-list],
.simpleDemo ul[dnd-list] > li {
position: relative;
}
.simpleDemo ul[dnd-list] {
min-height: 42px;
padding-left: 0px;
}
.simpleDemo ul[dnd-list] .dndDraggingSource {
display: none;
}
.simpleDemo ul[dnd-list] .dndPlaceholder {
display: block;
background-color: #ddd;
min-height: 42px;
}
.simpleDemo ul[dnd-list] li {
background-color: #fff;
border: 1px solid #ddd;
border-top-right-radius: 4px;
border-top-left-radius: 4px;
display: block;
padding: 10px 15px;
margin-bottom: -1px;
}
.simpleDemo ul[dnd-list] li.selected {
background-color: #dff0d8;
color: #3c763d;
}
This code is simply copied and pasted from the simple demo, just slightly modified to show lists A and B. Does anyone know what's wrong?
You're forgetting Dependency Injection just replace
angular.module("demo", [])
with
angular.module("demo", ['dndLists'])
and it should work..
plunk
--Update--
I found some problem with your Markup as well you are referencing list in <ul dnd-list="list>" this will not work as you're referencing an undefined variable, you should be referencing the list you are using in the drag-able. for example for the first list you can change.
<ul dnd-list="list">
to
<ul dnd-list="models.lists.A">
and that should work properly now..
P.S I've updated the plunk
you need the next: (that is the dependency injection)
app.requires.push('dndLists');
you are missing the ng-repeat in your angular it should look like this: (ng-repeat="(listName, list) in models.lists")
<div ng-repeat="(listName, list) in models.lists" class="col-md-6 ng-scope">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title ng-binding">List A</h3>
</div>
<div class="panel-body ng-scope">
<ul dnd-list="list" class="ng-scope">
<li ng-repeat="item in list"
dnd-draggable="item"
dnd-moved="list.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}"
dnd-disable-if="list.length < 2"
class="ng-binding ng-scope"
draggable="true">
{{item.label}}
</li>
</ul>
</div>
</div>
</div>
I have problem with swapping the dragged/dropped elements.
DOM / Angular Structure:
angular.module('app', ['ngDragDrop'])
.controller('controller', function($scope) {
$scope.listItems = [
{name: "some name", title: "title"},
{name: "some name2", title: "title2"},
];
$scope.input = {};
$scope.draggableOprions = {
revert: 'invalid'
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script src="https://cdn.jsdelivr.net/angular.dragdrop/1.07/angular-dragdrop.min.js"></script>
<div ng-app="app">
<div ng-controller="controller">
<div class="container">
<ul>
<li data-drag="true"
data-jqyoui-options="draggableOprions"
jqyoui-draggable="{animate:true}"
ng-model="item" ng-repeat="item in listItems track by $index">
{{item.title}}
</li>
</ul>
</div>
<div class="container"
data-drop="true"
data-jqyoui-options jqyoui-droppable
ng-model="input">
<input ng-model="input.name">
</div>
</div>
</div>
The problem:
While I drag and drop an list item 1 - the name property of the list item 1 comes to the input model. But no longer is available in list item 1. Actually the list item 1 value goes undefined || null after I drop it in the input. If I now try to drag-n-drop list item 2 item in the input - the values swapping (list item 1 = undefined || null ? and list item 2 = list item 1 value and input model equal to list item 2 value`. So everything shuffle.
What I need:
I need to drag and drop list items in the input, avoiding losing values in list items. Every time i drop list item in the input, I need it's value to bind to the input.
Out of the box
I can change the drag and drop library, or even use source code, but the library is the better choice. I accept almost every good working answer which didn't broke any standards of good code (I mean that I need code which will not broke the other code and has good structure).
I suggest to use ngDraggable, an Angular module with no depency from jQuery or jQuery-ui.
Here below is a working snippet or check my Codepen:
angular.module('app', ['ngDraggable'])
.controller('controller', function($scope) {
$scope.listItems = [{
name: "some name",
title: "title1"
}, {
name: "some name2",
title: "title2"
}, {
name: "some name3",
title: "title3"
}, ];
$scope.droppedObjects = [];
$scope.input = {};
// drag complete over drop area
$scope.onDragComplete = function(data, evt) {
console.log("drag success, data:", data);
var index = $scope.droppedObjects.indexOf(data);
if (index > -1) {
$scope.droppedObjects.splice(index, 1);
}
}
// drop complete over drop area
$scope.onDropComplete = function(data, evt) {
console.log("drop success, data:", data);
var index = $scope.droppedObjects.indexOf(data);
if (index == -1)
$scope.droppedObjects.push(data);
}
// drop complete over input box
$scope.onDropCompleteInput = function(data, evt) {
console.log("drop on input success, data:", data);
$scope.input = data;
}
// drop complete over items area (remove from dropped list)
$scope.onDropCompleteRemove = function(data, evt) {
console.log("drop success - remove, data:", data);
var index = $scope.droppedObjects.indexOf(data);
if (index != -1)
$scope.droppedObjects.splice(index);
}
// other draggable events handlers
var onDraggableEvent = function(evt, data) {
console.log("128", "onDraggableEvent", evt, data);
}
$scope.$on('draggable:start', onDraggableEvent);
//$scope.$on('draggable:move', onDraggableEvent);
$scope.$on('draggable:end', onDraggableEvent);
});
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
[ng-drag] {
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.item {
width: 100px;
height: 60px;
background: rgba(255, 0, 0, 0.5);
color: white;
text-align: center;
padding-top: 5%;
display: inline-block;
margin: 0 10px;
cursor: move;
}
ul.draggable-objects:after {
display: block;
content: "";
clear: both;
}
.draggable-objects li {
float: left;
display: block;
width: 120px;
height: 100px;
}
[ng-drag].drag-over {
border: solid 1px red;
}
[ng-drag].dragging {
opacity: 0.5;
}
.drop-container {
background: rgba(0, 255, 0, 0.5);
text-align: center;
width: 600px;
height: 200px;
padding-top: 90px;
display: block;
margin: 20px auto;
position: relative;
}
.drop-input {
width: 200px;
height: 40px;
}
.drag-enter {
border: solid 5px red;
}
.drop-container span.title {
display: block;
position: absolute;
top: 10%;
left: 50%;
width: 200px;
height: 20px;
margin-left: -100px;
margin-top: -10px;
}
.drop-container div {
position: relative;
z-index: 2;
}
<script src="//code.angularjs.org/1.4.8/angular.js"></script>
<script src="//rawgit.com/fatlinesofcode/ngDraggable/master/ngDraggable.js"></script>
<body ng-app="app">
<div ng-controller="controller">
<div class="row">
<h1>ngDraggable Example</h1>
</div>
<div ng-drop="true" ng-drop-success="onDropCompleteRemove($data,$event)">
<ul class="draggable-objects">
<li ng-repeat="obj in listItems">
<div ng-drag="true" ng-drag-data="obj" data-allow-transform="true" class="item"> {{obj.title}} </div>
</li>
</ul>
</div>
<hr/>
<div ng-drop="true" ng-drop-success="onDropComplete($data,$event)" class="drop-container">
<span class="title">Drop area</span>
<div ng-repeat="obj in droppedObjects" ng-drag="true" ng-drag-data="obj" ng-drag-success="onDragComplete($data,$event)" class="item">
{{obj.title}}
</div>
</div>
<hr/>
<div class="container">
Drop on input:
<input ng-model="input.name" class="drop-input" ng-drop="true" ng-drop-success="onDropCompleteInput($data,$event)">
</div>
<br>
<hr/>
<pre>listItems = {{listItems|json}}</pre>
<pre>input = {{input|json}}</pre>
<pre>droppedObjects = {{droppedObjects|json}}</pre>
</div>
</body>
<!DOCTYPE html>
<html>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script src="https://cdn.jsdelivr.net/angular.dragdrop/1.07/angular-dragdrop.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="MyController">
<div id="products">
<h1 class="ui-widget-header">Products</h1>
<div id="catalog">
<div>
<ul>
<li ng-repeat='item in list1' ng-show="item.title" data-drag="true" data-jqyoui-options="{revert: 'invalid', helper: 'clone'}" ng-model="list1" jqyoui-draggable="{index: {{$index}}, animate: true, placeholder: 'keep'}">{{item.title}}</li>
</ul>
</div>
</div>
</div>
<div id="cart">
<h1 class="ui-widget-header">Shopping Cart</h1>
<div class="ui-widget-content">
<ol data-drop="true" ng-model='list4' jqyoui-droppable="{multiple:true}">
<li ng-repeat="item in list4 track by $index" ng-show="item.title" data-drag="true" data-jqyoui-options="{revert: 'invalid', helper: 'clone'}" ng-model="list4" jqyoui-draggable="{index: {{$index}},animate:true}">{{item.title}}</li>
<li class="placeholder" ng-hide="hideMe()">Add your items here</li>
</ol>
</div>
</div>
</div>
<script>
var app = angular.module('myApp', ['ngDragDrop']);
app.controller('MyController', function ($scope,$http,$sce)
{
$scope.list1 = [{'title': 'Lolcat Shirt'},{'title': 'Cheezeburger Shirt'},{'title': 'Buckit Shirt'}];
$scope.list4 = [];
$scope.hideMe = function()
{
return $scope.list4.length > 0;
}
});
</script>
</body>
</html>
You have to use helper: 'clone' in data-jqyoui-options
My problem is that I have parents item that do not have children, they are called with their Id, the remaining called with her children-id
controller:
var listContent = angular.module('app', []);
listContent.controller('Cnt', function($scope) {
$scope.products = [{
"id": 10,
"name": "Samsung",
"children": [{
"id": 1122,
"name": "Galaxy S5"
}, {
"id": 1123,
"name": "Galaxy Note 4"
}, {
"id": 1124,
"name": "Galaxy S5 Mini"
}]
}, {
"id": 11,
"name": "LG",
"children": [{
"id": 25,
"name": "L70"
}, {
"id": 23,
"name": "G2"
}, {
"id": 24,
"name": "G3"
}]
}, {
"id": 12,
"name": "own",
"children": []
}];
});
**html code:**
<nav>
<div data-ng-class="procedures" data-ng-controller="Cnt">
<ul data-ng-repeat="parent in products">
<li>
<h4 data-ng-click="showDetails = ! showDetails">
<a>{{parent.name}}</a>
</h4>
** bei product "own", should call the parent-id , it should look like
<h4>
<a data-ng-href="http://....{{parent.id}}">{{parent.name}}</a>
</h4>
**
<ul class="procedure-details" data-ng-class="{ 'hidden': ! showDetails }">
<li data-ng-repeat="child in parent.children">
<a data-ng-href="http://....{{child.id}}">{{child.name}}</a>
</li>
</ul>
</li>
</ul>
</div>
</nav>
CSS
<style type="text/css">
li {
list-style: none;
padding: 0px;
border-bottom: 1px solid #eee;
}
.procedure-details {
max-height: 100px;
transition: .5s;
overflow: hidden;
background: #fff;
font-size: 13px;
}
.procedure-details.hidden {
max-height: 0;
}
ul {
margin: 0;
padding: 0;
}
nav {
font-family: Helvetica, Arial, "Lucida Grande", sans-serif;
line-height: 2;
width: 100%;
}
</style>
If I understand correctly, you want to have some html when a manufacturer has child products which shows links to all of those products. If a manufacturer does not have any products then you want to show a link to the manufacturer instead.
One way of doing this is using the ng-if directive to switch between different html.
<h4 ng-if="!parent.children.length">
<a data-ng-href="http://....{{parent.id}}">{{parent.name}}</a>
</h4>
<ul ng-if="parent.children.length" class="procedure-details" data-ng-class="{ 'hidden': ! showDetails }">
<li data-ng-repeat="child in parent.children">
<a data-ng-href="http://....{{child.id}}">{{child.name}}</a>
</li>
</ul>
This works because the length will be 0 if the array of children is empty, which is a falsey value.
Also consider using the ng-switch directive to better document the fact that these two sections of html are mutually exclusive.
Problem solved as follows :
<li data-ng-click="showDetails = ! showDetails">
<h4 data-ng-if="!parent.children.length">
{{parent.name}}
</h4>
<h4 data-ng-if="parent.children.length">
<a>{{parent.name}}</a>
</h4>
<ul class="procedure-details"
data-ng-class="{ 'hidden': ! showDetails }">
<li data-ng-click="showDetails = showDetails"
data-ng-repeat="child in parent.children"><a
data-ng-href="http://">{{child.name}}</a></li>
</ul>
</li>