Twitter Bootstrap Columns and Angular Order By - angularjs

I keep running into this problem and haven't found a good solution that doesn't cause layout issues. What's the best way to display an array of items, sorted alphabetically, in columns? I'm using ng-repeat to iterate over an array and display a checkbox for each item. I want the data to be displayed in n columns, alphabetically i.e., not alphabetically in rows.
alphabetically in colums
|item a| |item d| |item g|
|item b| |item e| ...
|item c| |item f| ...
current implementation - alphabetically in rows
<div class="checkbox col-xs-12 col-sm-12 col-md-3 col-lg-3" ng-repeat="user in user.results | orderBy:'lastName' track by user.id">
<input id="{{ user.id }}" type="checkbox">
{{ user.lastName }}, {{ user.firstName }}
<label for="{{ user.id }}" class="pull-left checkbox-label"></label>
</div>
Edit
I originally went with the dynamic bootstrap method but this actually screwed up the checkbox behavior i.e., clicking a checkbox resulted in the incorrect checkbox being checked. I'm trying fix this using flexbox but I haven't used it before and don't understand how to dynamically change the column count without having to set a fixed height on the flex container. I would like to have one column on small/extra small screens and three columns for medium/large screens.
.flex-box {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.flex-item {
background: green;
width: 33%;
}
/* Small screens */
#media all and (max-width: #container-tablet) {
.flex-item {
width: 100%;
}
}
<div class="flex-box">
<div class="flex-item" ng-repeat="country in region.countries | orderBy:'name' track by $index">
<input id="{{ country.isoCode }}" checklist-model="vm.selectedCountries.value[region.name]" checklist-value="country" type="checkbox" ng-change="vm.setRegionCountry(region, country, checked)">
<label for="{{ country.isoCode }}" class="pull-left checkbox-label"></label>
<span>{{ country.name | limitTo:17 }}{{country.name.length > 17 ? '...' : ''}}</span>
</div>
</div>
Solution
.flex-box {
display: flex;
flex-flow: column wrap;
}
/* Small screens */
#media all and (min-width: #screen-sm-min) {
.flex-box {
max-height: 375px;
}
}
/* Medium screens */
#media all and (min-width: #screen-md-min) {
.flex-box {
max-height: 550px;
}
}
/* Large screens */
#media all and (min-width: #screen-lg-min) {
.flex-box {
max-height: 375px;
}
}

You can tweak little bit as below if you want to use with bootstrap. Otherwise you can use either flex-box or column-count.
var app = angular.module('app', []);
app.controller('TestController', function($scope){
$scope.fixedColumn = 3;
$scope.getColumns = function(){
return new Array($scope.fixedColumn);
};
$scope.getColumnWidth = function(){
return Math.floor(12 / $scope.fixedColumn);
};
$scope.getRowCount = function(){
return Math.ceil($scope.user.results.length / $scope.fixedColumn);
};
$scope.user = {
results: [
{
id: 1,
firstName: 'FirstName1',
lastName: 'LastName1'
},
{
id: 2,
firstName: 'FirstName2',
lastName: 'LastName2'
},
{
id: 3,
firstName: 'FirstName3',
lastName: 'LastName3'
},
{
id: 4,
firstName: 'FirstName4',
lastName: 'LastName4'
},
{
id: 5,
firstName: 'FirstName5',
lastName: 'LastName5'
},
{
id: 6,
firstName: 'FirstName6',
lastName: 'LastName6'
},
{
id: 7,
firstName: 'FirstName7',
lastName: 'LastName7'
},
{
id: 8,
firstName: 'FirstName8',
lastName: 'LastName8'
}
]
};
});
angular.bootstrap(document, ['app']);
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-controller="TestController">
<div class="row" ng-repeat="u in user.results | orderBy:'lastName' track by u.id" ng-init="pIndex=$index" ng-if="$index < getRowCount()">
<div ng-repeat="col in getColumns() track by $index" ng-init="usr = user.results[pIndex + ($index * getRowCount())]" ng-class="'col-xs-'+ getColumnWidth() + ' col-sm-'+ getColumnWidth() + ' col-md-'+ getColumnWidth()" ng-if="user.results.length > (pIndex + ($index * getRowCount()))">
<input id="{{ usr.id }}" type="checkbox">
{{ usr.lastName }}, {{ usr.firstName }}
<label for="{{ usr.id }}" class="pull-left checkbox-label"></label>
</div>
</div>
</div>

<style>
.flex-box {
height: 100px;
overflow: hidden;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.flex-item {
background: green;
text-align: center;
}
</style>
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="flex-box">
<div class="flex-item" ng-repeat="user in user.results | orderBy:'lastName'">{{user.id}}</div>
</div>
</div>
</div>
</div>
Using CSS flexbox you can dynamically add as many column as required for your data set https://css-tricks.com/snippets/css/a-guide-to-flexbox/

You could do this without bootstrap using columns. See this fiddle: https://jsfiddle.net/ojzdxpt1/1/
#wrapper {
column-count:3;
-webkit-column-count:3;
-moz-column-count:3;
}
.col {
background:#ccc;
border:1px solid #000;
}
#wrapper contains each repeater. See more about css columns
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Columns/Using_multi-column_layouts
https://css-tricks.com/almanac/properties/c/columns/

Related

How to loop through 2-d array to display data on page?

This API is returning a 2-d array like this
I want to use these values to iterate and display on my page like this
I've looked through vue documentation but list rendering doesn't work. Is there any way I can do this with v-for or any other method?
There are two ways:
One is to convert array to the object array and iterate as v-for and value.date and value.price in v-for=" value in array"
[{
date: 'dd//mm/yy',
price: 3242,
}]
Other is to use array like this, written in a way elements in array should ] be constant, where value[0] is your price ad value[1] is your date.
<div v-for="value in array">
{{value[0]}} {{value[1]}}
</div>
If i understand you correctly, try like following snippet :
new Vue({
el: '#demo',
data(){
return {
sections: [
[699962583, 'Sep 17'],
[12665354, 'Sep 17'],
[739845240, 'Sep 17']
]
}
},
computed: {
currentPrize(){
// put logic to get current prize
return 6543210
}
}
})
ul {
display: flex;
flex-direction: column;
justify-content: center;
width: 300px;
}
li, .heading {
display: flex;
align-items: center;
justify-content: space-between;
}
h1, h3, h5 {
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<ul>
<h1>Past Prizes</h1>
<div class="heading">
<h5>Current prizes</h5><h3>$ {{ currentPrize }}</h3>
</div>
<li v-for="(section, index) in sections" :key="index">
<h5>{{ section[1] }}</h5><span>$ {{ section[0] }}</span>
</li>
</ul>
</div>
You can do it simply by looping over and destructing the sub-array in the v-for directive. Refer to the sample below:
Vue.config.productionTip = false
Vue.config.devtools = false
new Vue({
el: '#app',
data() {
return {
sections: [
[699962583, 'Sep 17'],
[12665354, 'Sep 17'],
[739845240, 'Sep 17']
]
}
},
computed: {
currentPrize() {
return this.sections.reduce(function(prev, current){ return prev += current[0]; }, 0);
}
}
})
ul {
list-style-type: none;
width: 400px;
}
li {
display: flex;
align-items: center;
justify-content: space-between;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h1>Past Prizes</h1>
<ul>
<li><span>Current prizes</span><span>${{ currentPrize }}</span></li>
<li v-for="([prize, date], index) in sections" :key="index">
<span>{{ date }}</span> <span>${{ prize }}</span>
</li>
</ul>
</div>

v-for render or dont render <div> on {x} iteration

I did not find solution to my question anywhere and I can't figure it out. I have divs like this
<div class="columns">
<div class="column">
{looping content here}
</div>
</div
Data is something like this:
{
title: 'blabla'
body: 'blabla'
msg: 'blabla"
}
For responsive purposes I need 3 columns max side by side and then start another columns container that will stack columns underneath. So 3 column divs inside columns container and then create another columns div with 3 column divs inside and go until the array is empty.
I have tried computed count property but don't know how to iterate it inside of v-for. Also tried v-if but it didnt work as planned :(
Is it even possible in v-for? I dont know what approach to take to be honest.
Why not just insert each column inside a single columns container and then use CSS to wrap to a new row every 3 columns. The added benefit of this is that you can adjust the number of columns that appear in each row with media queries.
Try running the snippet below in full screen and the resize the browser to less than 576px wide to see the responsive columns.
new Vue({
el: '#app',
data () {
return {
columns: [
{
title: 'blabla',
body: 'blabla',
msg: 'blabla'
},
{
title: 'blabla',
body: 'blabla',
msg: 'blabla'
},
{
title: 'blabla',
body: 'blabla',
msg: 'blabla'
},
{
title: 'blabla',
body: 'blabla',
msg: 'blabla'
},
{
title: 'blabla',
body: 'blabla',
msg: 'blabla'
}
]
}
}
})
.columns {
display: flex;
flex-wrap: wrap;
}
.column {
box-sizing: border-box;
padding: 1em;
width: 33.3%;
}
/* on devices smaller than 576px, stack columns */
#media (max-width: 576px) {
.column {
width: 100%;
}
}
<script src="https://unpkg.com/vue#2.6.8/dist/vue.min.js"></script>
<div id="app">
<div class="columns">
<div v-for="(column, index) in columns" class="column" :key="index">
<h2>{{ column.title }}</h2>
<p>{{ column.body }}</p>
<strong>{{ column.msg }}</strong>
</div>
</div>
</div>
It's possible to nest v-for loops if the data is correctly formatted.
For example, an array (for the first v-for) of objects (for the second loop):
new Vue({
el: "#app",
data() {
return {
items: [
{
title: 'Title 1',
body: 'body 1',
msg: 'message 1'
},
{
title: 'Title 2',
body: 'body 2',
msg: 'message 2'
}
]
}
}
})
.columns {
align-items: center;
display: flex;
height: 40px;
justify-content: space-around;
width: 50%;
}
<script src="https://unpkg.com/vue#2.6.8/dist/vue.min.js"></script>
<div id="app">
<div class="columns" v-for="item in items">
<div class="column" v-for="(value, key) in item">
<div>{{ value }}</div>
</div>
</div>
</div>

How can I create bind a list of elements as a group without ng-repeat?

I've been trying to learn Angular but hit a small blocker. My markup has a list of DIVs which when clicked get toggled (a new class). This is a static list of options and I would like to avoid the ng-repeat directive.
<div ng-app="sampleApp" ng-controller="MainCtrl">
<div class="item" id="germany">Germany</div>
<div class="item" id="poland">Poland</div>
<div class="item" id="sweden">Sweden</div>
<div class="item" id="japan">Japan</div>
<button type="button" ng-click="selected = []">Reset</button>
</div>
I would like to bind it to an array of selections. When clicked, the item's id should be added to the array and when unselected, it should be removed. The existence of the item's id in the selection array defines whether it should have the "active" class.
Below is how I've done it in Angular but this means that I cannot use my static list of DIVs but use the ng-repeat with the JSON. I've toyed around with this and got it correctly bound to the selected array. Clicking the button correctly resets the active class showing that the binding works.
Can I still accomplish this without going down the JSON + ng-repeat way? An example pointing me to this would be nice. Thank you
Here's the CSS:
.item {
border-color: #ddd;
background-color: #fff;
color: #444;
position: relative;
z-index: 2;
display: block;
margin: -1px;
padding: 16px;
border-width: 1px;
border-style: solid;
font-size: 16px;
}
.item.active {
border-color: #ccc;
background-color: #d9d9d9;
}
Here's the JS:
var SampleApp;
(function (SampleApp) {
var app = angular.module('sampleApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.selected = [];
$scope.clicked = function (member) {
var index = $scope.selected.indexOf(member.name);
if (index > -1) {
$scope.selected.splice(index, 1);
member.selected = false;
} else {
$scope.selected.push(member.name);
member.selected = true;
}
console.log($scope.selected);
}
$scope.items = [{
name: "item1"
}, {
name: "item2"
}, {
name: "item3"
}, {
name: "item4"
}, {
name: "item5"
}];
});
})(SampleApp || (SampleApp = {}));
Here's the markup:
<div ng-app="sampleApp" ng-controller="MainCtrl">
<div class="item" ng-repeat="item in items" ng-click="clicked(item)" ng-class="{ active: selected.indexOf(item.name) !== -1 }" id="item.name">{{ item.name }}</div>
<button type="button" ng-click="selected = []">Reset</button>
</div>
<div class="item" id="germany"
ng-click="toggle('germany')"
ng-class="{ active: selected.indexOf('germany') >= 0 }">Germany</div>
and repeat the same pattern for the other countries.
In the controller:
$scope.toggle = function(country) {
var index = $scope.selected.indexOf(country);
if (index >= 0) {
$scope.selected.splice(index, 1);
} else {
$scope.selected.push(country);
}
};
Not sure why you want to avoid ng-repeat though. Using it would avoid repeating the same code again and again in the view, and thus reduce the risk of introducing a bug.

Iterate through array via ngRepeat with breaks

I need your help.
I decided to make an attempt to create some kind of online market and I am somehow new to some parts of AngularJS and this is first time when I faced such a problem with ng-repeat.
I have the following html-structure (it is only a required part of it):
<div class="goods">
<div class="goods-row" ng-repeat="???">
<div class="good" ng-repeat="???">
<button id="add_to_cart">+</button>
<div class="descr">
<div class="descr-top">
<h5 class="g-name">
NAME IS HERE
</h5>
<span class="g-price">
PRICE IS HERE
</span>
</div>
<div class="descr-mid" ng-bind="good.description"></div>
</div>
</div>
</div>
</div>
"Goods"(goods-class) includes "rows of goods"(goods-row). Every row should include (by default) 4 goods (good-class), but, it should be also noticed that I will use filter, that could change number of visible goods in a row, because of that I need a flexible solution.
What should I enter in ng-repeat?
P.S. I created a blueprint with JS-code (posted below), that somehow shows what I want, but how to make it in AngularJS?
var arr = [];
for (i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
arr.push({
number: i
});
}
var divider = 4;
for (var i = 0; i < arr.length;) {
for (var j = 0; j < divider; j++) {
if ((j + i) < arr.length) {
console.log(arr[j + i]);
}
}
i = i + divider;
console.log(" ");
}
With lodash library you can use chunk function to split an array into chunks and then build a list that suits your needs.
So basically just iterate as you would do for a normal list of arrays (which represent your rows containing goods) and implement a function that build this list according to the divider. That way you can invoke the function when you need to rebuild your list (on keyup of the input in the example bellow) and let AngularJS do the rest.
(function(angular) {
'use strict';
angular.module('ngRepeat', [])
.controller('repeatController', function($scope) {
// the goods
$scope.goods = [
{ name: "name-1", price: 1.01, description: 'desc-1' },
{ name: "name-2", price: 2.02, description: 'desc-2' },
{ name: "name-3", price: 3.03, description: 'desc-3' },
{ name: "name-4", price: 4.04, description: 'desc-4' },
{ name: "name-5", price: 5.05, description: 'desc-5' },
{ name: "name-6", price: 6.06, description: 'desc-6' },
{ name: "name-7", price: 7.07, description: 'desc-7' },
{ name: "name-8", price: 8.08, description: 'desc-8' },
{ name: "name-9", price: 9.09, description: 'desc-9' },
{ name: "name-10", price: 10.10, description: 'desc-10' },
{ name: "name-11", price: 11.11, description: 'desc-11' },
{ name: "name-12", price: 12.12, description: 'desc-12' }
];
// divider determines how many goods per row (defaulted to 4)
$scope.divider = 4;
// function that build the rows of goods
$scope.dividerChanged = function() {
$scope.rows = _.chunk($scope.goods, $scope.divider);
};
// initialize rows on first load
$scope.dividerChanged();
});
})(window.angular);
.divider {
margin-bottom: 10px;
}
.goods-row {
border: 1px solid blue;
padding: 10px;
text-align: center;
}
.good {
border: 1px solid red;
display: inline-block;
padding: 10px;
margin: 10px;
width: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<body ng-app="ngRepeat">
<div ng-controller="repeatController">
divider: <input type="text" ng-model="divider" ng-keyup="dividerChanged()" class="divider">
<div class="goods">
<div class="goods-row" ng-repeat="row in rows">
<div class="good" ng-repeat="good in row">
<button id="add_to_cart">+</button>
<div class="descr">
<div class="descr-top">
<h5 class="g-name">{{ good.name }}</h5>
<span class="g-price">{{ good.price | currency }}</span>
</div>
<div class="descr-mid">{{ good.description }}</div>
</div>
</div>
</div>
</div>
</div>
</body>
I can't fully understand your question, are you trying to build a filtered array but always want to display the top 4 entries?
If yes, then it can be done with ng-repeat filter (custom or not) and limitTo filter
<div ng-repeat="data in test.data | customFilter:test.selectedFilter | limitTo:4">{{data}}</div>
https://jsbin.com/wajapabaro/1/edit?html,js,output

angular dragdrop (using jQuery UI) - disable swapping

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

Resources