Angular UI Sortable not working properly - javascript

I am working on Angular UI for making my menus sortable, sometimes the code works and sometimes its breaks like duplicating the entries or filling the blank menus when I am re arranging items.
Following is the full code -
<!doctype html>
<html lang="en" ng-app="myapp">
<head>
<title>Angular Sortable Demo</title>
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.min.js"></script>
<script>
var myapp = angular.module('myapp', ['ui']);
myapp.controller('controller', function ($scope) {
$scope.list = ["one", "two", "three", "four", "five", "six"];
});
//angular.bootstrap(document, ['myapp']);
</script>
</head>
<body>
<div ng:controller="controller">
<ul ui:sortable ng:model="list">
<li ng:repeat="item in list" class="item">{{item}}</li>
</ul>
<hr />
<div ng:repeat="item in list">{{item}}</div>
</div>
</body>
</html>
<style>
.item, .placeholder {
padding: 2px;
width: 50px;
height: 20px;
border: 1px solid #333;
background: #EEE;
}
.placeholder {
background: #AEF;
}
</style>
Also If someone could help me while creating this in JSFiddle as I tried this but unable to set it as a fiddle - Fiddle Link
EDIT-
This is how it becomes at times Screenshot (Menu Items duplicated)

I wrote my own directive (plnkr):
<ol dnd-list="wrap.names">
<li ng-repeat="name in wrap.names">{{name}} is {{$index}}</li>
</ol>
// directive for a single list
app.directive('dndList', function() {
return function(scope, element, attrs) {
// variables used for dnd
var toUpdate;
var startIndex = -1;
// watch the model, so we always know what element
// is at a specific position
scope.$watch(attrs.dndList, function(value) {
toUpdate = value;
},true);
// use jquery to make the element sortable (dnd). This is called
// when the element is rendered
$(element[0]).sortable({
items:'li',
start:function (event, ui) {
// on start we define where the item is dragged from
startIndex = ($(ui.item).index());
},
stop:function (event, ui) {
// on stop we determine the new index of the
// item and store it there
var newIndex = ($(ui.item).index());
var toMove = toUpdate[startIndex];
toUpdate.splice(startIndex,1);
toUpdate.splice(newIndex,0,toMove);
// we move items in the array, if we want
// to trigger an update in angular use $apply()
// since we're outside angulars lifecycle
scope.$apply(scope.model);
},
axis:'y'
})
}
});

Its Working Fine.... Take a look at this
Preview
JSFiddle
html
<div ng:controller="controller">
<ul ui:sortable ng:model="list">
<li ng:repeat="item in list" class="item">{{item}}</li>
</ul>
<hr />
<div ng:repeat="item in list">{{item}}</div>
</div>
script
var myapp = angular.module('myapp', ['ui']);
myapp.controller('controller', function ($scope) {
$scope.list = ["one", "two", "three", "four", "five", "six"];
});
angular.bootstrap(document, ['myapp']);

Related

Problem with ui-select with multiple and async options

I have a problem with the ui-select directive (AngularJS 1.6.4, Ui-select 0.19.8).
I have created the fiddle here.
It's supposed to show contacts in the dropdown I if type more than 3 chars. (I don't even try to filter anything at the moment, the same list of contacts is returned). It works well the first time, then the other times no dropdown is shown.
I use the async way of returning results so it calls my "refresh" function after 1sec.
Can someone help me understand why no dropdown is displayed after the first time ?
(also, if someone knows why I need to force the display: block for the <ul> tag - cf CSS )
Thanks
HTML
<body ng-app="myApp">
<div body ng-controller="ctrl as ctrl">
<div class="element">
Selected Contacts:<br>
<div ng-repeat="contact in ctrl.contacts" class="contact">
{{ contact }}
</div>
</div>
<ui-select multiple ng-model="ctrl.contacts" class="element">
<ui-select-match placeholder="Pick one...">{{$item}}</ui-select-match>
<ui-select-choices
position="down"
refresh="ctrl.refreshContacts($select.search)"
refresh-delay="1000"
minimum-input-length="3"
repeat="person in ctrl.people">
<div ng-bind-html="person | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
<div class="element">
<div ng-repeat="log in ctrl.logs track by $index" >
<div>
{{log}}
</div>
</div>
</div>
</div>
</body>
JS
var myApp = angular.module('myApp', ['ngSanitize','ui.select']);
myApp.controller("ctrl", [function () {
var ctrl = this;
ctrl.logs=[];
ctrl.refreshContacts = function(search) {
var people = [
"mickael",
"pierre",
"anna",
"alice",
"bob"
];
ctrl.people = people;
ctrl.logs.push("refreshContacts called")
}
ctrl.people = [];
}]);
CSS
.element {
margin-bottom: 20px;
}
.contact {
display: inline-block;
margin: 5px;
padding: 5px 8px;
background: grey;
}
/* why do I need this ?! */
.ui-select-choices {
display: block;
}
If I am remembering correctly there is a bug when using both minimum-input-length and refresh. I solved this problem by removing minimum-input-length and adding an if statement inside refresh function.
ctrl.refreshContacts = function(search) {
if(search == undefined || search.length < 3){
return;
}
else{
people = [
"mickael",
"pierre",
"anna",
"alice",
"bob"
];
ctrl.people = people;
}
}

I am trying to switch values in table cells using angularjs... can i use ngbind or ngmodel or something else?

I am trying to make a table cell clickable. When the cell is clicked it will switch the contents from one cell to another. I want to make a basic chess game out of this click action by eventually using angular.element to get the clicked elements and setting the second clicked square equal to the first clicked.html(). Is this possible in AngluarJs using a MEAN somehow?
My current code looks like this but the table cell isn't changing or doing anything when I click.
app.controller('ChessCtrl' , ['$http', '$scope', '$document', function
ChessCtrl($http, $scope, $document) {
var vm = this;
vm.test1 = angular.element(document.getElementById("A1"));
vm.test2 = "";
vm.test3 = "This is a test";
$scope.click = function() {
var temp = vm.test3;
vm.test2 = temp;
vm.test3 = "";
}
}]);
<div ng-Controller="ChessCtrl">
<div class="content">
<div class="left">
<table style="width: 75%">
<tr>
<td id="A1" ><a ng-bind="vm.test3" ng-click="click()"></a></td>
<td class="grey" ng-bind="vm.test2"><a ng-bind="vm.test2" ng-click="click()"></a>
</td>
<td>
</tr>
</table>
</div>
</div>
</div>
Obviously I am missing something but I have tried adding to a DB and pulling it back out. I have tried ng-model and ng-bind for holding the variables. I am just lost on if or how I can get the td to be clickable and also switch where what is clicked displays. Thanks!
NOTE: disregard test1 in this example... I was using that earlier for testing getting the HTML out of the element.
The HTML doesn't need the <a> tag. Simply set the CSS style to cursor: pointer.
Also the ng-bind directive isn't necessary, simply bind model to HTML with double brace {{ }} expressions.
The DEMO
angular.module("app",[])
.controller('ChessCtrl' , function () {
var vm = this;
vm.test2 = "♔";
vm.test3 = "test";
vm.switch = function() {
var temp = vm.test2;
vm.test2 = vm.test3;
vm.test3 = temp;
}
});
.red { background-color: red; }
.grey { background-color: grey; }
td {
width: 20%;
cursor: pointer;
font-size: 24pt;
}
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ChessCtrl as vm">
<table>
<tr>
<td class="red" ng-click="vm.switch()">{{vm.test3}}</td>
<td class="grey" ng-click="vm.switch()">{{vm.test2}}</td>
</tr>
</table>
</body>
Okay, I try to figure out one solution that might work for you too.
I am adding code snippet have a look:
Main challange, that you are facing is, ng-bind,
have a look to this article and find the sole purpose of ng-bind
https://www.w3schools.com/angular/ng_ng-bind.asp
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<table style="width: 75%">
<tr>
<td id="td1" ><a ng-bind="link1" ng-click="clickMe()"></a></td>
<td id="td2" class="" ><a ng-bind="link2" ng-click="clickMeAgain()"></a>
</td>
<td>
</tr>
</table>
</div>
<script>
var clickMeIsClicked = false;
var clickMeAgainIsClicked = false;
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.link1 = 'Click me to show td2';
$scope.link2 = ' I always want to be visible, thanks td1';
$scope.count = 0;
$scope.myFunction = function() {
$scope.count++;
}
$scope.clickMe = function(){
if(!clickMeIsClicked){
$scope.link2 = 'Click me to show td2';
$scope.link1 = ' I always want to be visible, thanks td1';
clickMeIsClicked = true;
}
else{
$scope.link1 = 'Click me to show td2';
$scope.link2 = ' I always want to be visible, thanks td1';
clickMeIsClicked = false;
}
}
$scope.clickMeAgain = function(){
}
});
</script>
</body>
</html>

Problems with calling a function in the HTML file using Angular JS

I am fairly new with AngularJS. I'm trying to do something simple for the moment. I created a table with some text I'll have to search with, a reset button (In my program is called "Pulisci") and some panels I'll have to use later. The problem is that, if I call the function I created for resetting the page, the panels mysteriously stop working. I'm banging my head on this since last week.
HTML
<!DOCTYPE html>
<html ng-app="sbi">
<head>
<link rel="stylesheet" type="text/css" href="bootstrap.min.css">
<style>
table,
td {
border-width: 2px;
border-collapse: collapse;
padding: 15px;
color: #000000;
text-align: center;
}
table.pos_fixed1 {
position: relative;
top: 30px;
left: 10px;
}
</style>
</head>
<body>
<form name="form">
<table summary="" width="10%" class="pos_fixed1" align="center">
<tr>
<td>Code Subinstaller<br><input name="codeSub" type="text" ng-model="codeSub"></td>
<td>Stato<br>
<select>
<option value="1">...</option>
<option value="2">WHITE LIST</option>
<option value="3">GRAY LIST</option>
</select>
</td>
</tr>
<tr>
<td>Nome Sub Installer<input name="nomeSub" type="text" ng-model="nomeSub"></td>
<td>Cognome Sub Installer<input name="cognSub" type="text" ng-model="cognSub"></td>
<td>Codice Fiscale<input name="codFisc" type="text" ng- model="codFisc"> </td>
</tr>
</table><br>
<button class="btn btn-wide btn-default.active.focus" data-ng- click="">Cerca</button>
<button class="btn btn-wide btn-default.active.focus" data-ng- click="reset()">Pulisci</button>
</form><br><br>
<section ng-controller="PanelController as panel">
<ul class="nav nav-pills">
<li ng-class="{ active:panel.isSelected(1) }"> <a href ng- click="panel.selectTab(1)">Description</a></li>
<li ng-class="{ active:panel.isSelected(2) }"> <a href ng- click="panel.selectTab(2)">Specifications</a></li>
<li ng-class="{ active:panel.isSelected(3) }"> <a href ng- click="panel.selectTab(3)">Reviews</a></li>
</ul>
<div class="panel" ng-show="panel.isSelected(1)">
<h4>Description </h4>
<p>wtf</p>
</div>
<div class="panel" ng-show="panel.isSelected(2)">
<h4>Idk</h4>
<p>Idc</p>
</div>
<div class="panel" ng-show="panel.isSelected(3)">
<h4>APPARI</h4>
<p>???</p>
</div>
</section>
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript" src="myapp.js"></script>
</body>
</html>
JS
(function() {
var app = angular.module('sbi', []);
app.controller('PanelController', function() {
this.tab = 1;
this.selectTab = function(setTab) {
this.tab = setTab;
};
this.isSelected = function(checkTab) {
return this.tab === checkTab;
};
});
})();
(function($scope) {
var app = angular.module('sbi', []);
function MyCtrl($scope) {
$scope.reset = function() {
$scope.requiredField = '';
};
};
});
How can I make the Reset() and the panels work simultaneously?
You have re-initialized your angular module.
Initializing your angular module
var app = angular.module('sbi', []);
Second argument in angular.module() is for injecting the required dependency for the module. And hence should be done only once.
In your code, you have again initialized your module.
(function () {
//initialization
var app = angular.module('sbi', []);
app.controller('PanelController', function () {
this.tab = 1;
this.selectTab = function (setTab) {
this.tab = setTab;
};
this.isSelected = function (checkTab) {
return this.tab === checkTab;
};
});
})();
(function ($scope) {
//edit in your code
//re-using the already initialized module
var app = angular.module('sbi');
function MyCtrl($scope) {
$scope.reset = function () {
$scope.requiredField = '';
};
};
});
You should not pass the second argument as parameter.
Reusing your angular module
var app = angular.module('sbi');
EDIT :
Try the following code :
(function () {
var app = angular.module('sbi', []);
app.controller('PanelController', ['$scope', function($scope) {
$scope.tab = 1;
$scope.selectTab = function (setTab) {
$scope.tab = setTab;
};
$scope.isSelected = function (checkTab) {
return $scope.tab === checkTab;
};
$scope.reset = function () {
$scope.requiredField = '';
};
}]);
})();
There is something you are clearly missing here: your reset function is attached to... nothing.
The MyCtrl function is never called (from what we've seen), and the $scope variable is not injected the Angular-way. Actually, nothing here is in the Angular way. Let me try to adjust this so you understand what you should aim for.
First of all, as #Akshay mentioned, there is a huge difference between angular.module('something', []) and angular.module('something'), but they already pointed that out in their response.
Then, your MyCtrl hasn't been registered as a controller in Angular. You just defined the function, you were missing these lines:
var app = angular.module('sbi');
function MyCtrl($scope) {
$scope.reset = function () {
$scope.requiredField = '';
};
};
// This controller will be known as 'MyCtrl'
app.controller('MyCtrl', MyCtrl);
This should work. Note that you won't be needing the surrounding (function ($scope) {...}) as it won't be executed correctly.
Then, you will have to tell Angular to use that controller in that specific part of your page:
<!-- Adding the ng-controller directive here -->
<form name="form" ng-controller="MyCtrl">
...
<button class="btn btn-wide btn-default.active.focus" data-ng-click="reset()">Pulisci</button>
</form>
Then, you will be able to handle your requiredField variable as you wish.

rounded corners and highlight the selected one

I am working on angularJS application. I have a webpage with multiple tabs created using angularJs.
Please find the working tabs example : http://plnkr.co/edit/jHsdUtw6IttYQ24A7SG1?p=preview
I want to show the border of all the tabs with rounded corners and highlight the selected tab as shown in the image below. I tried using css but could not achieve as expected. Please suggest.
Code:
<html>
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.5.0.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<style>
.nav-tabs>.active>a, .nav-tabs>.active>a:hover, .nav-tabs>.active>a:focus {
background-color: pink;
}
.pageSecTitle,.sel td:nth-child(2) {
border: 0;
}
td select {
vertical-align: top;
}
</style>
<script>
//controller for tabs
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller("TabsParentController", function ($scope) {
var setAllInactive = function() {
angular.forEach($scope.workspaces, function(workspace) {
workspace.active = false;
});
};
$scope.workspaces =
[
{ id: 1, name: "Tab1", active:true},
{ id: 2, name: "Tab2", active:false},
{ id: 3, name: "Tab3", active:false}
];
$scope.addWorkspace = function () {
setAllInactive();
};
});
app.controller ("TabsChildController", function($scope, $log){
});
</script>
</head>
<body>
<br><br>
<div ng-controller="TabsParentController">
<tabset>
<tab ng-repeat="workspace in workspaces"
heading="{{workspace.name}}"
active=workspace.active>
<div ng-controller="TabsChildController">
--some dynamic content here--
</div>
</tab>
</tabset>
</div>
</body>
</html>
Try adding this css rule to the css you already have:
.nav-tabs>li>a, .nav-tabs>li>a:hover, .nav-tabs>li>a:focus {
border: 1px solid red;
}
It should add a red border for all inactive tabs. You can add a border to the active tab by adding to the css rule you currently use to set the background pink.

Controller in Nested views of AngularJS

Iam new to AngularJS and was stuck at the concept of angular nested views with single controller. Gone through some examples here, which didn't help me. Below is the code from a question and I need 2 things here. After clicking on submit:
1.The date selected has to be assigned as input and url has to be constructed based on the date selected and the result from that url has to be displayed in Modal.
2.At the same time a table(present in tab-submit.html) has to displayed in the page(in tab.html) below the submit button from another URL.
Below is the code I have in app.js:
wc.controller('MyController', function ($scope, $modal, $log, $http, $location, $filter) {
var that = this;
var in10Days = new Date();
in10Days.setDate(in10Days.getDate() + 10);
$scope.dates = {
date3: " "
};
this.dates = {
date3: new Date()
};
this.open = {
date3: false
};
// Disable weekend selection
this.disabled = function (date, mode) {
return (mode === 'day' && (new Date().toDateString() == date.toDateString()));
};
this.dateOptions = {
showWeeks: false,
startingDay: 1
};
this.timeOptions = {
readonlyInput: false,
showMeridian: false
};
this.dateModeOptions = {
minMode: 'year',
maxMode: 'year'
};
this.openCalendar = function (e, date) {
that.open[date] = true;
};
$scope.format = 'yyyy-MM-dd%20HH:mm';
debugger;
$scope.open = function () {
var date = $filter("date")($scope.dates.date3, $scope.format);
$http.get(http://myurlPartA+date+"myurlPartB")
.success(function (response) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function () {
return response;
}
}
});
});
};
});
var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
$scope.items = items;
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
Here is a plunker:http://plnkr.co/edit/xKbkFGoa3p5y5NAzueut?p=preview. Is it possible to get solution for my question??Hope anyone will help me to understand this.
Thanks in advance!!
Requirements
1. Have a page with two tabs
2. If click the tab1, should load the page with date picker and a submit button
3. After selecting a date picker I will click the submit button
4. Then from a url I should get the data for particular date which I have selected.
5. There will be two api calls, one for modal and one for table
6. Then modal should show up with the data
7. After closing the modal, table should below the submit button
As I understood from your discussion, I think this is what you wanted to do.
Have a page with two tabs
If click the tab1, should load the page with date picker and a submit button
After selecting a date picker I will click the submit button
Then from a url I should get the data for particular date which I have selected.
There will be two api calls, one for modal and one for table
Then modal should show up with the data
After closing the modal, table should below the submit button
I saw few issues in your codes.
Some issues in Directive, the way you use
Getting data from api
How you open and close the modal
How you print data in table
I have a updated, working Plunker here.
Please find the below code changes. In the codes you are getting the codes for Modal. but I dont know how you will bind it. Please change it as you want.
index.html
<!DOCTYPE html>
<html>
<head>
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
li {
float: left;
}
li a {
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover {
background-color: darkgrey;
}
</style>
<link rel="stylesheet" type="text/css" href="jquery.datetimepicker.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.datetimepicker.full.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
<script src="ui-bootstrap-tpls.js"></script>
<script src="datetime-picker.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.min.js"></script>
<script src="application.js"></script>
</head>
<body ng-app="wc">
<ul>
<li><a ui-sref="tab">Tab1</a></li>
<li><a ui-sref="tabs">Tab2</a></li>
</ul>
<div class="container">
<div ui-view></div>
</div>
</body>
</html>
application.js
var wc = angular.module('wc', ['ui.router','ui.bootstrap', 'ui.bootstrap.datetimepicker']);
wc.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/posts');
$stateProvider
.state('tab', {
url: '/tab1',
templateUrl: 'tab.html'
})
.state('tabs', {
url: '/tabs',
templateUrl: 'tabs.html',
});
});
wc.controller('SampleController', function ($scope, $http, $modal) {
$scope.subt_click = function () {
//Selected Date is here use as you want
//$scope.mydate
alert($scope.mydate);
//Modal Data
$http.get("http://jsonplaceholder.typicode.com/posts")
.success( function(response) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalController',
resolve: {
items: function () {
return response;
}
}
});
});
//Table Data
$http.get("http://jsonplaceholder.typicode.com/posts")
.success( function(response) {
$scope.tableData = response;
});
};
});
wc.controller('ModalController', function ($scope, $modalInstance, items) {
$scope.modalData = items;
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
wc.directive('datetimepicker', function () {
return {
require: 'ngModel',
link: function (scope, el, attr, ngModel) {
$(el).datetimepicker({
onSelect: function (dateText) {
scope.$apply(function () {
ngModel.$setViewValue(dateText);
});
}
});
}
};
});
Tab.html
<div class="jumbotron text-top" ng-controller="SampleController">
<h4>Select from below:</h4>
<form class="form-horizontal">
<input datetimepicker="" ng-model="mydate" type="text" readonly-input="true" />
<a class="btn btn-info" ng-click="subt_click()">Submit</a>
</form>
<div class="table-responsive" ng-show="tableData.length > 0">
<table class="table table-striped table-bordered table-hover dataTables-example">
<thead>
<tr>
<th>ID</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in tableData">
<td>{{x.id}}</td>
<td>{{x.body}}</td>
</tr>
</tbody>
</table>
</div>
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>Info</h3>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="x in modalData">
{{ x.id + '-' + x.title}}
</li>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="cancel()">Close</button>
</div>
</script>
$stateProvider is best used for navigating to an entirely different page in your app . For modals , dom animations ect .. This should be put in a directive .
Example
wc.directive('modal', function(){
return {
restrict: "A",
template: 'modal.html' // FYI the html for the actual modal popup
link: function(scope,elem,attrs){
$(".modal").show();
}
}
})
for instance ; in your modal.html would contain something like this
<div class="modal" style="display:none;">
</div>
then in your main document
<div modal></div>
//Or you can place this on whatever element you desire to show the modal

Categories