So i am developing this app in which i want to apply pagination to list of templates.
template objects are stored in the list.
I am displaying thumbnails of templates on the page and i want to apply pagination for this page.
so far I have tried following solution but it didn't work.
list.html
<div class="container">
<div class="homepage-header">
<h2 class="homepage-title text-center wow fadeInDown animated" style="visibility: visible; animation-name: fadeInDown; -webkit-animation-name: fadeInDown;"> TEMPLATES </h2>
</div>
<div class="row">
<div class="col-md-6 col-sm-6" style="text-align: left">
<div class="form-inline">
<div class="form-group has-feedback has-clear">
<input type="text" class="form-control" ng-model="searchParam" ng-model-options="{ debounce: 400 }" placeholder="Search template ..."
/>
<a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" ng-click="searchParam = '';
retreivePageData(0);" ng-show="searchParam" style="pointer-events: auto; "></a>
</div>
</div>
</div>
<div class="col-md-6 col-sm-6" style="text-align: right; padding-right: 30px;">
<div class="form-inline">
<label>
<input type="radio" ng-model="selectedOption" value="All" ng-change="retrieveTemplates(selectedOption)"> All
</label>
<label>
<input type="radio" ng-model="selectedOption" value="Annotate" ng-change="retrieveTemplates(selectedOption)"> Annotate
</label>
<label>
<input type="radio" ng-model="selectedOption" value="Rapid" ng-change="retrieveTemplates(selectedOption)"> Component
</label>
</div>
</div>
</div>
<div class="homepage-ui-showcase-2-css row wow zoomIn animated" style="height: 402px;padding: 5px 0px; visibility: visible; animation-name: zoomIn; -webkit-animation-name: zoomIn;">
<div ng-repeat="(templateIndex, templateModel) in templatesList | filter:searchParam | limitTo: itemsPerPage">
<div class="active col-md-3 col-lg-3 col-sm-6 col-xs-12 mix design painting" style="display: inline-block;padding-top: 10px;"
ng-init="visible=false" ng-mouseover="visible=true" ng-mouseleave="visible=false">
<div class="portfolio-item shadow-effect-1 boxShadow" style="max-width: 250px;padding:0.3px;border:2px dotted #bebede;cursor: pointer">
<div class="mainBadge">
<kbd>{{templateModel.type}}</kbd>
</div>
<div ng-switch on="{{templateModel.type !== undefined && templateModel.type === 'Annotate'}}">
<div ng-switch-when="false" style="height: 130px;" ui-sref="/designer/:pageId({pageId:templateModel.id})" class="portfolio-img ">
<i style="opacity:0.4;padding-top:35px;padding-left:15px;margin-left: 30%;" class="fa fa-puzzle-piece fa-4x"></i>
</div>
<div ng-switch-when="true" style="height: 130px;" ui-sref="annotator/:annotatedTemplateId({annotatedTemplateId:templateModel.id})"
class="portfolio-img ">
<i style="opacity:0.4;padding-top:35px;padding-left:15px;margin-left: 30%;" class="fa fa-file-image-o fa-4x"></i>
</div>
</div>
<div class="portfolio-item-content" title="{{templateModel.name}}">
<h3 class="header" style="font-size: 13px;text-align: center;display:inline;">
{{templateModel.name}}
</h3>
<small class="pull-right" ng-show="visible" style="display: inline; padding-top: 4px">
<div ng-switch on="{{templateModel.type !== undefined && templateModel.type === 'Annotate'}}">
<div ng-switch-when="true" href="#" class="btn btn-xs btn-danger" title="Generate Communication"
ui-sref="generateCommunication({mode:'A',id: templateModel.id})"
ng-disabled="!templateModel.dynamic_entity"> <!--style="color:#9d9d9;"-->
<i class="fa fa-file-pdf-o"></i>
</div>
<div ng-switch-when="false" href="#" class="btn btn-xs btn-danger" title="Generate Communication"
ui-sref="generateCommunication({mode:'T',id: templateModel.id})"
ng-disabled="!templateModel.dynamic_entity"> <!--style="color:#9d9d9;"-->
<i class="fa fa-file-pdf-o"></i>
</div>
</div>
</small>
</div>
</div>
</div>
</div>
</div>
<div class="row " style="margin-top: 10px; padding-top:0px;">
<div class="pagination-div pull-right" style="">
<uib-pagination ng-model="currentPage" total-items="totalItems" max-size="maxSize" boundary-links="true">
</uib-pagination>
</div>
</div>
list.controller.js
'use strict';
angular.module('rapid').controller('HomeListController',
function($scope, $rootScope, $window, $uibModal, ServiceFactory, toaster, ReadFileService, AnnotationService, AnnotateService, DocumentService) {
$scope.templatesList = [];
$scope.filteredTemplates = [];
$scope.selectedOption = 'All';
$scope.annotateTemplateMeta = [];
$scope.rapidTemplateMeta = [];
$scope.init = function() {
$scope.selectedOption = "All";
//$scope.options = [{'label':'All', 'value':'All'}, {'label':'Annotate', 'value':'Annotate'}, {'label':'Component', 'value':'Component'}];
$scope.retrieveTemplates('All');
$scope.currentPage = 1;
};
$scope.retrieveTemplates = function(selectedOption) {
$scope.templatesList = [];
if (selectedOption === 'Annotate') {
$scope.fetchAnnotationTemplates(selectedOption);
} else if (selectedOption === 'Rapid') {
$scope.fetchRapidTemplates(selectedOption);
} else {
$scope.fetchAnnotationTemplates(selectedOption);
}
};
$scope.fetchAnnotationTemplates = function(selectedOption) {
AnnotateService.get().$promise.then(function(result) {
$scope.annotateTemplateMeta = result[0];
console.log('Annotated template count :: ' + result[0].length);
if (selectedOption === 'All') {
$scope.fetchRapidTemplates(selectedOption);
} else {
$scope.prepareTemplateList(selectedOption);
}
});
};
$scope.fetchRapidTemplates = function(selectedOption) {
ServiceFactory.PagesService.getAllPages().$promise.then(function(result) {
$scope.rapidTemplateMeta = result[0];
console.log('Rapid template count :: ' + result[0].length);
$scope.prepareTemplateList(selectedOption);
});
};
$scope.prepareTemplateList = function(selectedOption) {
$scope.itemsPerPage = 8;
var getPaginatedTemplateList = 'getList';
//$scope.currentPage = 0;
if (selectedOption === 'Annotate') {
$scope.annotateTemplateMeta.forEach(function(annotate) {
var templateObject = {};
templateObject = { id: annotate.id, name: annotate.name, type: "Annotate", dynamic_entity: annotate.dynamic_entity };
$scope.templatesList.push(templateObject);
});
} else if (selectedOption === 'Rapid') {
$scope.rapidTemplateMeta.forEach(function(rapidTemplate) {
var templateObject = {};
templateObject = { id: rapidTemplate._id, name: rapidTemplate.name, type: "Component", dynamic_entity: rapidTemplate.pageObj.entity };
$scope.templatesList.push(templateObject);
});
} else {
$scope.annotateTemplateMeta.forEach(function(annotate) {
var templateObject = {};
templateObject = { id: annotate.id, name: annotate.name, type: "Annotate", dynamic_entity: annotate.dynamic_entity };
$scope.templatesList.push(templateObject);
});
$scope.rapidTemplateMeta.forEach(function(rapidTemplate) {
var templateObject = {};
templateObject = { id: rapidTemplate._id, name: rapidTemplate.name, type: "Component", dynamic_entity: rapidTemplate.pageObj.entity };
$scope.templatesList.push(templateObject);
});
$scope.totalItems = $scope.templatesList.length;
$scope.maxSize = 5;
}
console.log($scope.templatesList);
console.log($scope.currentPage);
};
$scope.setPage = function(pageNo) {
$scope.currentPage = pageNo;
};
$scope.pageChanged = function() {
alert('Page changed to: ' + $scope.currentPage);
$log.log('Page changed to: ' + $scope.currentPage);
};
$scope.init();
$scope.$watch('currentPage + numPerPage', function() {
console.log('is it coming.....?');
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage)
, end = begin + $scope.itemsPerPage;
$scope.filteredTemplates = $scope.templatesList.slice(begin, end);
});
});
is there anything wrong with my code?
please provide some inputs on this.
See how to create a custom paging which will deal with the performance and you will have control on the paging control style.
Create a service to set a paging object
var rapid = angular.module('rapid');
rapid.service('pagerOptions', function () {
'use strict';
return {
newOptions: function () {
return {
totalItems: 0,
itemsPerPage: 50,
page: 1,
sortBy: '',
isASC: true,
filters: null,
sortOptions: {
by: '',
isASC: true,
sort: function (sortBy) {
if (sortBy === this.parent.sortBy) {
this.parent.isASC = !this.parent.isASC;
} else {
this.parent.sortBy = sortBy;
this.parent.isASC = true;
}
this.parent.resetPage();
if (typeof this.parent.onPageChange === "function")
this.parent.onPageChange();
}
},
resetPage: function () {
this.page = 1;
},
goToPage: function (page) {
this.page = page;
if (typeof this.onPageChange === "function")
this.onPageChange();
},
init: function () {
this.sortOptions.parent = this; // it allows the Methods object to know who its Parent is
delete this.init; // if you don't need the Init method anymore after the you instanced the object you can remove it
return this; // it gives back the object itself to instance it
}
}.init();
}
};
})
Create a custom directive to design paging template as follows,
rapid.directive('footerPager', function () {
return {
restrict: 'E',
transclude: true,
template:
'<div class="col-xs-9 text-right" ng-cloak>\
<span ng-if="options.totalItems > options.itemsPerPage">\
<pagination \
ng-model="options.page" \
total-items="options.totalItems" \
items-per-page="options.itemsPerPage" \
ng-change="options.goToPage(options.page)" \
max-size="5" rotate="false" boundary-links="true" \
previous-text="‹" next-text="›" \
first-text="«" last-text="»" \
class="pagination-sm">\
</pagination>\
</span>\
</div>\,
scope: {
options: '='
}
}
});
In cshtml file use the above created custom directive as follows,
<footer-pager options="pagingOptions" id="footer"/>
In corresponding controller.js file create and set the 'pagerOptions' object by calling the 'newOptions' method of the above created service,
rapid.controller('HomeListController',
['$scope', 'adminSvc','pagerOptions',
function auditLogCtrl($scope,adminSvc,pagerOptions) {
$scope.pagingOptions = pagerOptions.newOptions();
$scope.pagingOptions.sortBy = "CreatedDate";
$scope.pagingOptions.itemsPerPage = 10;
$scope.pagingOptions.onPageChange = loadData; //loadData is a method load the data to the page.
var numberOfSearchPerfomed = 0;
$scope.data= {};
function loadData() {
$scope.pagingOptions.filters = selectedFilters;
service.getData(vm.pagingOptions) //Method will fetch data from db and show in the view based on pagingOptions.
.success(function (result) {
$scope.data= result.Data;
$scope.pagingOptions.totalItems = result.TotalCount; // TotalCount represents the total number of records not page wise.
$scope.enableResetButton = numberOfSearchPerfomed >= 1;
});
}
loadData();
}])
Related
I would like to use two different divs one contains a form and other contains repeat for the $scope values. Those two divs needs to use the same controller. However I am not able to share data in between divs in a desired way. Although I use factory, it only helps for me to add data to scope. I also want to edit the scope values inside the form which has another instance of the same controller.
You can find what I did in this link.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<body>
<script>
var app = angular.module("myShoppingList", []);
app.factory('fact',function(){
products = ["milk","chese"];
tempItem = '';
tempIndex = undefined;
return {
getProducts : function() {
return products;
},
getProductByIndex : function(x){
return products[x];
},
saveProduct : function(x,item)
{
if(x==undefined)
{
products.push(item);
}
else
{
products[x] = item;
}
tempItem = '';
tempIndex = undefined;
},
editProduct : function(x)
{
tempItem = products[x];
tempIndex = x;
},
removeProduct : function(x)
{
products.splice(x, 1);
},
getTempItem : function()
{
return tempItem;
},
getTempIndex : function()
{
return tempIndex;
},
}
});
app.controller("myCtrl", function($scope, fact) {
$scope.products = fact.getProducts();
$scope.tempIndex = fact.getTempIndex();
$scope.tempItem = fact.getTempItem();
$scope.saveItem = function () {
fact.saveProduct($scope.tempIndex,$scope.tempItem);
}
$scope.editItem = function (x) {
fact.editProduct(x);
}
$scope.removeItem = function (x) {
fact.removeProduct(x);
}
});
</script>
<div ng-app="myShoppingList" ng-cloak class="w3-card-2 w3-margin" style="max-width:400px;">
<header class="w3-container w3-light-grey w3-padding-16">
<h3>My Shopping List</h3>
</header>
<div ng-controller="myCtrl">
<ul class="w3-ul">
<li ng-repeat="x in products" class="w3-padding-16">{{$index}} {{x}}
<span ng-click="editItem($index)" style="cursor:pointer;" class="w3-right w3-margin-right">||</span>
<span ng-click="removeItem($index)" style="cursor:pointer;" class="w3-right w3-margin-right">×</span>
</ul>
</div>
<div ng-controller="myCtrl" class="w3-container w3-light-grey w3-padding-16">
<form ng-submit="saveItem()">
<div class="w3-row w3-margin-top">
<div class="w3-col s10">
<input placeholder="Add shopping items here" ng-model="tempItem" class="w3-input w3-border w3-padding">
<input type="hidden" ng-model="tempIndex">
</div>
<div class="w3-col s2">
<button type="submit" class="w3-btn w3-padding w3-green">Save</button>
</div>
</div>
</form>
</div>
</div>
</body>
</html>
ISSUES
You have initialized controller twice.
You can do edit item inside controller itself.
After saving $scope values should be cleared along with clearing values in factory.
CONTROLLER and HTML
var app = angular.module("myShoppingList", []);
app.factory('fact',function(){
products = ["milk","chese"];
tempItem = '';
tempIndex = undefined;
return {
getProducts : function() {
return products;
},
getProductByIndex : function(x){
return products[x];
},
saveProduct : function(x,item)
{
if(!x)
{
products.push(item);
}
else
{
products[x] = item;
}
tempItem = '';
tempIndex = '';
},
editProduct : function(x)
{
tempItem = products[x];
tempIndex = x;
},
removeProduct : function(x)
{
products.splice(x, 1);
},
getTempItem : function()
{
return tempItem;
},
getTempIndex : function()
{
return tempIndex;
},
}
});
app.controller("myCtrl", function($scope, fact) {
$scope.products = fact.getProducts();
$scope.tempIndex = fact.getTempIndex();
$scope.tempItem = fact.getTempItem();
$scope.saveItem = function () {
fact.saveProduct($scope.tempIndex,$scope.tempItem);
$scope.tempItem = '';
$scope.tempIndex = '';
}
$scope.editItem = function (x) {
$scope.tempItem = fact.getProducts()[x];
$scope.tempIndex = x;
}
$scope.removeItem = function (x) {
fact.getProducts().splice(x, 1);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<div ng-app="myShoppingList" ng-controller="myCtrl" ng-cloak class="w3-card-2 w3-margin" style="max-width:400px;">
<header class="w3-container w3-light-grey w3-padding-16">
<h3>My Shopping List</h3>
</header>
<div>
<ul class="w3-ul">
<li ng-repeat="x in products" class="w3-padding-16">{{$index}} {{x}}
<span ng-click="editItem($index)" style="cursor:pointer;" class="w3-right w3-margin-right">||</span>
<span ng-click="removeItem($index)" style="cursor:pointer;" class="w3-right w3-margin-right">×</span>
</ul>
</div>
<div class="w3-container w3-light-grey w3-padding-16">
<form ng-submit="saveItem()">
<div class="w3-row w3-margin-top">
<div class="w3-col s10">
<input placeholder="Add shopping items here" ng-model="tempItem" class="w3-input w3-border w3-padding">
<input type="hidden" ng-model="tempIndex">
</div>
<div class="w3-col s2">
<button type="submit" class="w3-btn w3-padding w3-green">Save</button>
</div>
</div>
</form>
</div>
</div>
I'm trying to send a DELETE request by using the angular-resource service, but I keep getting the following message in dev tools:
Error: message.$delete is not a function
$scope.deleteMessage#file:///Users/me/Desktop/angular/my-app/loyalty-program_messages-pointstransactions.js:37:13
anonymous/fn#file:///Users/me/Desktop/angular/my-app/angularjs/angular.js line 14605 > Function:2:329
expensiveCheckFn#file:///Users/me/Desktop/angular/my-app/angularjs/angular.js:15694:18
ngEventHandler/https://code.jquery.com/jquery-1.12.4.min.js:3:12392
n.event.add/r.handle#https://code.jquery.com/jquery-1.12.4.min.js:3:9156
I notice that the angular-resource is missing here. Is there a reason for this?
This is the module with the controller:
var myApp = angular.module('myApp', ['ngResource'])
.constant("baseUrl1", MY-TESTING-URL-1)
.config(function($httpProvider) {
$httpProvider.defaults.withCredentials = true;
})
myApp.controller("MessagesCtrl", function($scope, $http, $resource, baseUrl1){
$scope.displayMode = "list";
$scope.currentMessages = null;
$scope.messagesResource = $resource(MY-TESTING-URL-1 + ":id?projection=full", { id: "#id" });
$scope.listMessages = function () {
$scope.foo = $scope.messagesResource.get();
$scope.foo.$promise.then(function (data) {
$scope.messages = [];
for(var i = 0; i < $scope.foo._embedded.messages.length; i++) {
var obj = $scope.foo._embedded.messages[i];
$scope.messages.push(obj);
}
});
}
$scope.deleteMessage = function (message) {
message.$delete().then(function () {
$scope.messages.splice($scope.messages.indexOf(message), 1);
});
$scope.displayMode = "list";
}
$scope.createMessage = function (message) {
new $scope.messagesResource(message).$save().then(function(newMessage) {
$scope.messages.push(newMessage);
$scope.displayMode = "list";
});
}
$scope.updateMessage = function (message) {
message.$save();
$scope.displayMode = "list";
}
$scope.editOrCreateMessage = function (message) {
$scope.currentMessage = message ? message : {};
$scope.displayMode = "edit";
}
$scope.saveEdit = function (message) {
if (angular.isDefined(message.id)) {
$scope.updateMessage(message);
} else {
$scope.createMessage(message);
}
}
$scope.cancelEdit = function () {
if ($scope.currentMessage && $scope.currentMessage.$get) {
$scope.currentMessage.$get();
}
$scope.currentMessage = {};
$scope.displayMode = "list";
}
$scope.listMessages();
});
This is the view with the ng-click that SHOULD send a DELETE request:
<div ng-repeat="message in messages">
<div class="data-tables read-{{ message.read }}">
<div class="data-tables-rows">
<div class="data-tables-toggle" type="button" data-toggle="collapse" data-target="#collapse_disclaimer_data-table_message-center_{{ $index }}" aria-expanded="false" aria-controls="collapse_disclaimer_data-table_message-center_{{ $index }}" title="View Details">
<label></label>
</div>
<div class="data-table-message hidden-xs" type="button" data-toggle="collapse" data-target="#collapse_disclaimer_data-table_message-center_{{ $index }}" aria-expanded="false" aria-controls="collapse_disclaimer_data-table_message-center_{{ $index }}" title="View Details">
<p style="white-space: nowrap; width: inherit; overflow: hidden;text-overflow: ellipsis;"><b>message</b><br />
{{ message.message }}
</p>
</div>
<div class="data-table-date" type="button" data-toggle="collapse" data-target="#collapse_disclaimer_data-table_message-center_{{ $index }}" aria-expanded="false" aria-controls="collapse_disclaimer_data-table_message-center_{{ $index }}" title="View Details">
<p><b>date</b><br />
<date>{{ message.dateReceived | date }}</date>
</p>
</div>
<div class="data-table-points hidden-xs points-{{ message.metadata }}" type="button" data-toggle="collapse" data-target="#collapse_disclaimer_data-table_message-center_{{ $index }}" aria-expanded="false" aria-controls="collapse_disclaimer_data-table_message-center_{{ $index }}" title="View Details">
<p><b>Points</b><br />
{{ message.metadata }}</p>
</div>
<div class="data-table-delete">
<button ng-click="deleteMessage(message)">Delete</button>
</div>
</div>
<div class="collapse" id="collapse_disclaimer_data-table_message-center_{{ $index }}">
<div class="data-tables-rows">
<div class="data-tables-spacer" style="visibility:hidden;">
<input id="data-table-icon" type="checkbox" />
<label for="data-table-icon"></label>
</div>
<div class="well">
<div class="data-table-message">
<p><b>Message</b><br />
{{ message.message }}</p>
</div>
<div class="data-table-points visible-xs">
<p><b>Points</b><br />
{{ message.metadata }}</p>
</div>
</div>
<div class="data-tables-spacer">
</div>
</div>
</div>
</div>
The message comes from CDN served JSON:
{
"_embedded": {
"messages":
{
"id": 8,
"message": "You received points",
"dateReceived": "2016-08-01T00:00:00.000+0000",
"read": false,
"metadata": "50"
}
}
}
Firefox in debugger option 'Selection to watch expression' doesn't appear to reveal anything abnormal as the object data is listed. Please help!
Thank you Joaozito Polo, you helped us figure it out. var newMessage is the new object from resource. Here is the new listMessages function:
$scope.listMessages = function () {
$scope.foo = $scope.messagesResource.get();
$scope.foo.$promise.then(function (data) {
$scope.messages = [];
for(var i = 0; i < $scope.foo._embedded.messages.length; i++) {
var obj = $scope.foo._embedded.messages[i];
var newMessage = new $scope.messagesResource(obj)
$scope.messages.push(newMessage);
}
});
}
There are two types of data I'm displaying on single page, one is Insert form and second is where the data is displayed with the help of Angular dataTables, now what I want to do is when I click on Edit I wana display the Data within the Insert form Fields also change the Save button from Save to Update... I've tried it but I'm getting this error although its displaying the data in console.
controller.js:1356 24
controller.js:1363 Colony 02 2
angular-1.4.8.js:12520 TypeError: Cannot set property 'colony_name' of undefined
NOTE: Insert, Delete, Displaying Data is working fine.
Here is my HTML PAGE
<div class="row-fluid" ng-controller="colony_Controller">
<div class="span12">
<div class="span6">
<!-- WIDGET START -->
<div class="widget TwoWidgetsInOneFix">
<!-- Widget Title Start -->
<div class="widget-title">
<h4><i class="icon-reorder"></i>Add Colony</h4>
<span class="tools">
<!-- -->
</span>
</div>
<!-- Widget Title End -->
<!-- Widget Body Start -->
<div class="widget-body">
<form class="form-horizontal">
<div class="control-group">
<div class="small-bg-half">
<label class="control-label">Colony Name</label>
<div class="controls">
<input type="text" class="input-xlarge" id="" autofocus required name="colony_name"
ng-model="field.colony_name" > <!-- ng-->
<span class="help-inline" id="help-inline" style="color:red;"></span>
</div>
</div>
</div>
<div class="control-group">
<div class="small-bg-half">
<label class="control-label">Colony Type</label>
<div class="controls">
<select data-toggle="status" class="select select-default mrs mbm input-xlarge" name="colony_type" id="colony_type" ng-model="field.colony_type_id" required> <!-- ng -->
<option value="">--Select Colony Type--</option>
<option ng-repeat="colony in es_colony_type" value="{{colony.es_colony_type_id}}">{{colony.es_colony_type_name}}</option>
</select>
</div>
</div>
</div>
<div class="form-actions">
<button type="button" class="btn btn-success" ng-click="InsertData()"> <!-- ng -->
<i class="icon-plus icon-white"></i> Save</button>
</div>
</form>
</div>
<!-- Widget Body End -->
</div>
<!-- WIDGET END -->
</div>
<div class="span6">
<!-- WIDGET START -->
<div class="widget TwoWidgetsInOneFix">
<!-- Widget Title Start -->
<div class="widget-title"> <!-- ng -->
<h4><i class="icon-reorder"></i>List Of Colony</h4>
<span class="tools">
<!-- -->
</span>
</div>
<!-- Widget Title End -->
<!-- <div id="alert-2" flash-alert active-class="in alert" class="fade">
<strong class="alert-heading">Boo!</strong>
<span class="alert-message">{{flash.message}}</span>
</div> -->
<!-- Widget Body Start -->
<div class="widget-body">
<div ng-controller="colony_Controller as Main_Module">
<table class="table table-striped table-bordered" align="center" datatable="" dt-options="Main_Module.dtOptions" dt-columns="Main_Module.dtColumns" class="row-border hover">
</table>
</div>
</div>
</div>
<!-- Widget Body End -->
</div>
<!-- WIDGET END -->
</div>
Here is my Controller
Main_Module.controller('colony_Controller', function add_house_Controller(flash, $window, $scope, $http, $compile, DTOptionsBuilder, DTColumnBuilder, bootbox, SimpleHttpRequest, DelMainRecPicRecUnlinkPic, message)
{
$http.get('http://localhost:3000/api/SELECT/es_colony_type').success(function(data)
{
$scope.es_colony_type = data.es_colony_type;
});
/********************************** FETCH DATA END *********************************/
/********************************** INSERT DATA START ********************************/
$scope.InsertData = function()
{
var values = $scope.field;
SimpleHttpRequest.Insert('POST','INSERT', 'es_colony', values)
.then(function successCallback(response)
{
if(!response.data.Error)
{
message.successMessageForInsert("<strong>Successfull !</strong> Colony Details Inserted");
setTimeout(function()
{
$window.location.reload();
}, 3500);
// flash.to('alert-1').success = 'Only for alert 1';
}
else
{
message.failedMessageForInsert("<strong>Error !</strong> Data Insertion Failed");
}
},
function errorCallback(response)
{
message.failedMessageForInsert("<strong>Error!</strong> Data Insertion Failed !");
});
};
/********************************** INSERT DATA END **********************************/
/********************************** DISPLAY DATA START *******************************/
var vm = this;
vm.dtOptions = DTOptionsBuilder
.fromFnPromise(function()
{
return $http.get('http://localhost:3000/api/SELECT/es_colony')
.then(function(response)
{
return response.data.es_colony;
});
})
.withOption('order', [0, 'asc'])
.withDisplayLength(5)
.withPaginationType('simple_numbers')
.withOption('createdRow', function(row, data, dataIndex)
{
$compile(angular.element(row).contents())($scope);
})
vm.dtColumns =
[
DTColumnBuilder.newColumn('es_colony_name').withTitle('Colony'),
DTColumnBuilder.newColumn(null).withTitle('Actions').notSortable().withOption('width', '31%')
.renderWith(function(data, type, full, meta)
{
return '<button class="btn btn-primary" ng-click="edit_records(' + data.es_colony_id + ')">' +
'<i class="icon-edit"></i> Edit' + '</button> ' +
'<button class="btn btn-danger" ng-click="DeleteRecord(' + data.es_colony_id + ')">' +
'<i class="icon-remove icon-white"></i> Delete' + '</button>';
})
];
/********************************** DISPLAY DATA END *********************************/
/********************************** DELETE DATA START ********************************/
// $scope.hideRow = [];
$scope.DeleteRecord = function(id)
{
bootbox.confirm("Are you sure you want to delete this Record ?", function (confirmation)
{
if(confirmation)
{
DelMainRecPicRecUnlinkPic.DeleteIt('', id, true, 'es_colony', 'es_colony_id')
{
setTimeout(function()
{
$window.location.reload();
}, 3500);
};
}
});
};
$scope.edit_records = function(id)
{
// PassId.id = id;
console.log(id);
SimpleHttpRequest.SelectByID('GET', 'SELECTBYID', 'es_colony', 'es_colony_id', id)
.then(function successCallback(response)
{
var data = response.data.es_colony[0];
console.log(data.es_colony_name, data.es_colony_type_id);
$scope.ufield.ucolony_name = data.es_colony_name;
$scope.ufield.colony_type_id = data.es_colony_type_id;
});
};
/********************************** DELETE DATA END **********************************/
});
In your template, you have an input with ng-model="field.colony_name", but in your controller you never defined $scope.field. You do assign the value var values = $scope.field inside the $scope.InsertData function, but that will just set values to undefined.
Try initializing the variable by adding $scope.field = {} to the beginning of your controller, for starters. That will resolve the error you are getting.
Here is the code that may help you.
Html:
<div ng-app="myApp" ng-controller="MainCtrl">
<fieldset data-ng-repeat="choice in choices">
<input type="text" ng-model="choice.name" name="" placeholder="Enter mobile number"> <button class="remove" ng-show="$last" ng-click="removeChoice()">-</button>
</fieldset>
<button class="addfields" ng-click="addNewChoice()">Add fields</button>
<div id="choicesDisplay">
{{ choices }}
</div>
</div>
Js:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.choices = [{id: 'choice1'}, {id: 'choice2'}];
$scope.addNewChoice = function() {
var newItemNo = $scope.choices.length+1;
$scope.choices.push({'id':'choice'+newItemNo});
};
$scope.removeChoice = function() {
var lastItem = $scope.choices.length-1;
$scope.choices.splice(lastItem);
};
});
Also CSS:
fieldset{
background: #FCFCFC;
padding: 16px;
border: 1px solid #D5D5D5;
}
.addfields{
margin: 10px 0;
}
#choicesDisplay {
padding: 10px;
background: rgb(227, 250, 227);
border: 1px solid rgb(171, 239, 171);
color: rgb(9, 56, 9);
}
.remove{
background: #C76868;
color: #FFF;
font-weight: bold;
font-size: 21px;
border: 0;
cursor: pointer;
display: inline-block;
padding: 4px 9px;
vertical-align: top;
line-height: 100%;
}
input[type="text"],
select{
padding:5px;
}
Html
<div ng-app="albumShelf">
<div ng-controller="MainCtrl">
<div style="float:left;">
<select ng-options="b.title for b in albums" ng-model="currentAlbum" ng-change="onChange()">
<option value="">New album...</option>
</select>
</div>
<div style="float:left;">
<form>
<input type="text" ng-model="editing.title">
<br>
<input type="text" ng-model="editing.artist">
<br>
<input type="submit" value="{{ currentAlbum.title ? 'Update' : 'Save' }}" ng-click="addOrSaveAlbum()">
</form>
</div>
</div>
</div>
Js:
var app= angular.module('myApp', [])
.controller('MainCtrl', ['$scope', function($scope/*, albumFactory*/) {
$scope.editing = {};
$scope.albums = [
{ id: 1, title: 'Disorganized Fun', artist: 'Ronald Jenkees' },
{ id: 2, title: 'Secondhand Rapture', artist: 'MS MR' }
];
$scope.addOrSaveAlbum = function() {
if ($scope.currentAlbum) {
$scope.currentAlbum.title = $scope.editing.title;
$scope.currentAlbum.artist = $scope.editing.artist;
}else {
$scope.albums.push({ title: $scope.editing.title, artist: $scope.editing.artist });
}
$scope.editing = {};
};
$scope.onChange = function() {
if ($scope.currentAlbum) {
$scope.editing.title = $scope.currentAlbum.title;
$scope.editing.artist = $scope.currentAlbum.artist;
}else {
$scope.editing = {};
}
};
}])
I have a modal service in my app that opens/closes a modal. When the modal is opened, it plucks its content from the div with the specified id, which always sits inside a container elem that is hidden. Normally this works fine.
The problem I'm having now is that when a user opens the modal with the mediaBrowser directive for the first time, they can navigate between the photos/videos tab and select an item to attach to a post. If the modal is closed and reopened though, nothing works. The photos load as expected, but clicking one does nothing. It's as if none of the functions in the mediaBrowser or mediaBrowserPhotos directive work.
I thought it might have something to do with needing to compile the directive after its moved from one DOM element to another, but I've not had much luck resolving it with the $compile service.
Here is my modal service:
app.service('modal', [function() {
var modal = this;
modal.settings = {};
modal.overlay = $('<div id="overlay"></div>');
modal.modal = $('<div id="modal"></div>');
modal.content = $('<div id="content"></div>');
modal.closeBtn = $('<div id="close"><i class="fa fa-times"></div>');
modal.modal.hide();
modal.overlay.hide();
modal.modal.append(modal.content, modal.closeBtn);
$(document).ready(function(){
$('body').append(modal.overlay, modal.modal);
});
modal.open = function (settings) {
modal.settings = settings;
var content = modal.settings.content;
modal.content.empty().append(content);
if(modal.settings.class) modal.modal.addClass(modal.settings.class);
if(modal.settings.height) modal.modal.css({ height: settings.height });
if(modal.settings.width) modal.modal.css({ width: settings.width });
if(modal.settings.content_height) modal.modal.css({ height: settings.content_height });
if(modal.settings.content_width) modal.modal.css({ width: settings.content_width });
if(modal.settings.fitToWindow) {
modal.settings.width = $(window).width() - 160;
modal.settings.height = $(window).height() - 160;
};
center(modal.settings.top);
$(window).bind('resize.modal', center);
modal.modal.show();
modal.overlay.show();
$(modal.closeBtn).add(modal.overlay).on('click', function(e) {
e.stopPropagation();
modal.close();
});
$(document).on('keyup', function(e) {
if (e.keyCode == 27) {
modal.close();
$(document).unbind('keyup');
}
})
};
modal.close = function() {
var elem = modal.settings.elem;
var content = modal.settings.content;
elem.empty().append(content);
modal.modal.hide();
modal.overlay.hide();
modal.content.empty();
$(window).unbind('resize.modal');
};
function center(top) {
if(!top || !isInt(top)) top = 130;
var mLeft = -1 * modal.modal.width() / 2;
modal.modal.css({
top: top + 'px',
left: '50%',
marginLeft: mLeft
});
function isInt(n) {
return n % 1 === 0;
}
}
}]);
I also have a mediaBrowser directive in my app, which housed 2 child directives representing a photos and videos tab. Here is my mediaBrowser directive:
app.directive('mediaBrowser', ['$rootScope', 'profileAPI', 'photosAPI', 'videosAPI', function($rootScope, profileAPI, photosAPI, videosAPI) {
return {
replace: true,
templateUrl: '/assets/employers/media_browser.html',
scope: {
model: '=',
card: '=',
type: '=',
photoContainer: '=',
videoContainer: '=',
mediaBrowserContainer: '=',
mediaBrowserForm: '='
}, controller: ['$scope', '$rootScope', 'profileAPI', 'photosAPI', 'videosAPI', function($scope, $rootScope, profileAPI, photosAPI, videosAPI) {
$scope.mediaView = profileAPI.mediaView;
resize($scope.mediaView);
$rootScope.$on('mService:keyChanged', function resultsUpdated(event, value) {
$scope.mediaView = profileAPI.mediaView;
resize($scope.mediaView);
});
$scope.setMediaView = function(view) {
profileAPI.mediaView = view;
};
function resize(resource) {
if(resource === 'photos') {
photosAPI.resizeColumns('#media_browser_photos_new_' + $scope.type);
} else if (resource === 'videos') {
videosAPI.resizeColumns('#media_browser_videos_new_' + $scope.type);
}
}
}]
}
}]);
Here is the partial for the mediaBrowser directive:
<div style="display:none" id="{{mediaBrowserContainer}}">
<div id="{{mediaBrowserForm}}">
<div class="row">
<div class="col-lg-12">
<div class="row subheader modal-tabs">
<ul class="nav navbar-nav">
<li ng-class="{'active-sub': mediaView === 'photos'}">
<a ng-click="setMediaView('photos');">Photos</a>
</li>
<li ng-class="{'active-sub': mediaView === 'videos'}">
<a ng-click="setMediaView('videos');">Videos</a>
</li>
</ul>
</div>
</div>
</div>
<div class="row" ng-if="mediaView === 'photos'">
<div media-browser-photos
model="model"
container="photoContainer"
media-browser-container="mediaBrowserContainer"
media-browser-form="mediaBrowserForm"
for-type="type"
mode="'new'">
</div>
</div>
<div class="row" ng-if="mediaView === 'videos'">
<div media-browser-videos
model="model"
container="videoContainer"
media-browser-container="mediaBrowserContainer"
media-browser-form="mediaBrowser"
for-type="type"
mode="'new'">
</div>
</div>
</div>
</div>
Here is my mediaBrowserPhotos directive. Note that the videos version is basically identical to photos:
app.directive('mediaBrowserPhotos', ['$rootScope', '$timeout', '$q', 'photosAPI', 'modal', function($rootScope, $timeout, $q, photosAPI, modal) {
return {
replace: true,
templateUrl: '/assets/employers/media_browser_photos.html',
scope: {
container: '=',
model: '=',
mediaBrowserContainer: '=',
mediaBrowserForm: '=',
forType: '=',
mode: '='
}, controller: ['$scope', '$rootScope', '$timeout', '$q', 'photosAPI', 'modal', function($scope, $rootScope, $timeout, $q, photosAPI, modal) {
$scope.current_page = photosAPI.current_page;
$scope.results = [];
$scope.loading = false;
$scope.num_pages = 0;
$scope.page_numbers = photosAPI.page_numbers;
$scope.total_count = 0;
$scope.count = 0;
$scope.order = false;
var thumbSize = 150;
var q = $scope.current_page;
$rootScope.$on('cService:keyChanged', function resultsUpdated(event, value) {
$scope.results = photosAPI.results;
$scope.loading = photosAPI.loading;
$scope.num_pages = photosAPI.num_pages;
$scope.page_numbers = photosAPI.page_numbers;
$scope.total_count = photosAPI.total_count;
});
$scope.selectMedia = function(options) {
if($scope.mode === 'new') {
var content = '#add_card_form';
var elem = '#add_card_form_container';
} else {
var content = '#' + $scope.forType + '_' + $scope.model.id + '_form';
var elem = '#' + $scope.forType + '_' + $scope.model.id + '_form_container';
};
$scope.model[options.type] = options.object;
modal.close();
modal.open({
content: $(content),
elem: $(elem),
height: '594px',
content_height: '578px'
})
}
}]
}
}]);
Here is the partial for mediaBrowserPhotos:
<div class="column-layout cols-3 search-results-no-resize" id="{{container}}">
<div class="multiple-photo-upload media">
<button type="button" class="btn btn-default dropdown-toggle" ng-click="orderAsc();">
Sort by Date
Oldest First <i class="fa fa-arrow-up" style="font-size: 1.3em;"></i>
Newest First <i class="fa fa-arrow-down" style="font-size: 1.3em;"></i>
</button>
<div class="paginator" ng-if="page_numbers.length > 1">
<div class="page-btn prv" ng-click="prevPage()"><i class="fa fa-chevron-left"></i></div>
<div class="page-btn" ng-repeat="p in page_numbers" ng-class="{'current':p === current_page}" ng-click="loadPage(p)">{{p}}</div>
<div class="page-btn nxt" ng-click="nextPage()"><i class="fa fa-chevron-right"></i></div>
</div>
</div>
<div class="results-label media"><b>{{total_count}}</b> <span ng-if="total_count == 1">Photo</span><span ng-if="total_count != 1">Photos</span></div>
<div class="media-browser photos" ng-show="!loading && total_count > 0">
<div class="col">
<div ng-repeat="r in results" class="card result-link">
<div class="content result">
<div class="image-container" ng-style="{'background-image': 'url(' + r.image_url + ')'}" ng-click="$parent.selectMedia({object: r, type: 'image'})"></div>
</div>
</div>
</div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<br style="clear:both" />
</div>
<div ng-show="loading" class="loading-results">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
The whole app itself is pretty complex and difficult to reproduce in a Plucker/Fiddle. Any help would be greatly appreciated. Let me know of you need any additional code from the app!
Try this: instead of moving the whole thing, wrap it in another element, leave that one in place and move the same element you were moving now (now the child of the element in your link function).
If you don't use replace:true, which is deprecated anyway, you get that element for free (the directive's element).
Good luck!
I have a MVC view that has bootstrap navtabs in it. On each tab a different view loads. They are called delayed spiff, and instantspiff. I have added a datepicker and a button that should display data in the 2 views. The only problem is that when I click my button the views don't refresh. They keep their original data instead of the new data based on the date. I need to somehow reload the view after the date is selected and then show the new data. I'll share some of my code. Here's my code:
Main view:
<div class="container-fluid delayed_spiff_main">
<div class="row-fluid 1">
<div class="col-lg-12 delayed_spiff_body">
<div class="row spiff-datepicksection">
<div class="col-lg-6 pull-right">
<div class="col-sm-5 col-lg-offset-4">
<div class="form-group">
<div class="input-group date">
<input type="text" id="startDate" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<div class="col-lg-3">
<input class="spiffdate-btn" type="button" value="Submit" />
</div>
</div>
</div>
<div class="row spiff_tabs_body">
<!-- Nav tabs -->
<ul class="nav nav-tabs spiff_tabs" role="tablist">
<li role="presentation" class="active">
Potential Spiff
</li>
<li role="presentation">
Instant Spiff
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="delayedspiff"></div>
<div role="tabpanel" class="tab-pane" id="instantspiff"></div>
</div>
</div>
</div>
</div>
<script>
$(function () {
FormGet('dashboard/delayedspiff', 'delayedspiff');
});
</script>
javascript to load details in view:
function pullDetails(carrierId, startDate, status, divid) {
$.get("#Url.Action("getDelayedSpiffOrderDetails", "Dashboard")",
{ carrierId: carrierId, startDate: startDate, status: status },
function (data) {
$('.' + divid + ' .submitted_details').html(data);
$('.' + divid).removeClass('carrier-hide');
});
}
And just to make this even more confusing here is my Controller code:
public ActionResult DelayedSpiff(DateTime? startDate)
{
var available = _appService.GetFeatureStatus(1, "spiffDashboard");
if (!available)
return RedirectToAction("DatabaseDown", "Error", new { area = "" });
//var startDate = DateTime.Today.AddDays(-6);
if (!startDate.HasValue || startDate.Value == DateTime.MinValue)
{
startDate = DateTime.Today.AddDays(-7);
}
else
{
startDate = startDate.Value.AddDays(-7);
}
var acctId = User.AccountID;
var endDate = DateTime.Today.AddDays(1); // 1
Dictionary<DateTime, List<SpiffSummaryModel>> dict = new Dictionary<DateTime,List<SpiffSummaryModel>>();
try
{
var properties = new Dictionary<string, string>
{
{ "Type", "DelayedSpiff" }
};
telemetry.TrackEvent("Dashboard", properties);
dict = _reportingService.GetDailyDelayedSpiffSummaries(acctId, startDate.Value, endDate);
}
catch (Exception e)
{
if (e.InnerException is SqlException && e.InnerException.Message.StartsWith("Timeout expired"))
{
throw new TimeoutException("Database connection timeout");
}
var error = _errorCodeMethods.GetErrorModelByTcError(PROJID.ToString("000") + PROCID.ToString("00") + "001", "Exception Getting DelayedSpiff Dashboard View", PROJID, PROCID);
error.ErrorTrace = e.ToString();
_errorLogMethods.LogError(error);
return RedirectToAction("index", "error", new { error = error.MaskMessage });
}
var spiffDateModels = new List<DelayedSpiffDateModel>();
foreach (var entry in dict)
{
var spiffDateModel = new DelayedSpiffDateModel();
spiffDateModel.Date = entry.Key;
spiffDateModel.Carriers = new List<DelayedSpiffCarrierModel>();
foreach (var item in entry.Value)
{
var spiffCarrierModel = new DelayedSpiffCarrierModel();
spiffCarrierModel.Carrier = item.CarrierName;
spiffCarrierModel.CarrierId = item.CarrierId;
spiffCarrierModel.ApprovedSpiffTotal = item.ApprovedSpiffTotal;
spiffCarrierModel.EligibleActivationCount = item.EligibleActivationCount;
spiffCarrierModel.IneligibleActivationCount = item.IneligibleActivationCount;
spiffCarrierModel.PotentialSpiffTotal = item.PotentialSpiffTotal;
spiffCarrierModel.SubmittedActivationCount = item.SubmittedActivationCount;
spiffCarrierModel.UnpaidSpiffTotal = item.UnpaidSpiffTotal;
spiffDateModel.Carriers.Add(spiffCarrierModel);
}
spiffDateModels.Add(spiffDateModel);
}
spiffDateModels = spiffDateModels.OrderByDescending(x => x.Date).ToList();
return PartialView(spiffDateModels);
}
UPDATE code that loads inside of tabpanel:
<div class="container-fluid">
<div class="row">
<div class="col-lg-11 col-center-block delayspiffdata" id="details">
<table class="delay_spiff_tbl">
<thead>
<tr>
<th class="blank"></th>
<th>Submitted Activations / Potential Spiff</th>
<th>Approved Activations / Approved Spiff</th>
<th>Ineligible Activations / Unpaid Spiff</th>
</tr>
</thead>
<tbody>
#for (int date = 0; date < Model.Count; date ++)
{
<tr class="date-row" onclick="$('.date_#date').toggleClass('date-hide');">
<td class="spiffdate">
#Model[date].Date.ToString("dddd MM/dd/yyyy")
<i class="fa fa-plus-circle expander_open" ></i>
</td>
<td>#Model[date].Carriers.Sum(c => c.SubmittedActivationCount) / #Model[date].Carriers.Sum(c => c.PotentialSpiffTotal).ToString("C")</td>
<td>#Model[date].Carriers.Sum(c => c.EligibleActivationCount) / #Model[date].Carriers.Sum(c => c.ApprovedSpiffTotal).ToString("C")</td>
<td>#Model[date].Carriers.Sum(c => c.IneligibleActivationCount) / #Model[date].Carriers.Sum(c => c.UnpaidSpiffTotal).ToString("C")</td>
</tr>
for (int carrier = 0; carrier < Model[date].Carriers.Count; carrier++)
{
<tr class="date_#date date-hide" onclick="$('.submitted-#date-#carrier').toggleClass('carrier-hide');">
<td><span class="pull-left dash"><i class="fa fa-caret-up"></i></span> #Model[date].Carriers[carrier].Carrier</td>
<td>
<a onclick="pullDetails('#Model[date].Carriers[carrier].CarrierId', '#Model[date].Date', 'potential' ,'submitted-#date-#carrier')">
#(Model[date].Carriers[carrier].SubmittedActivationCount == 0 ? "--" :
Model[date].Carriers[carrier].SubmittedActivationCount + " / " +
Model[date].Carriers[carrier].PotentialSpiffTotal.ToString("C"))
</a>
</td>
<td>
<a onclick="pullDetails('#Model[date].Carriers[carrier].CarrierId', '#Model[date].Date', 'eligible' ,'submitted-#date-#carrier')">
#(Model[date].Carriers[carrier].EligibleActivationCount == 0 ? "--" :
Model[date].Carriers[carrier].EligibleActivationCount + " / " +
Model[date].Carriers[carrier].ApprovedSpiffTotal.ToString("C"))
</a>
</td>
<td>
<a onclick="pullDetails('#Model[date].Carriers[carrier].CarrierId', '#Model[date].Date', 'ineligible' ,'submitted-#date-#carrier')">
#(Model[date].Carriers[carrier].IneligibleActivationCount == 0 ? "--" :
Model[date].Carriers[carrier].IneligibleActivationCount + " / " +
Model[date].Carriers[carrier].UnpaidSpiffTotal.ToString("C"))
</a>
</td>
</tr>
<tr class="date_#date date-hide submitted-#date-#carrier carrier-hide carrier">
<td class="submitted_details" colspan="100%">
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
<script>
$(function () {
$('.date-row').click(function () {
$(this).find('i').toggleClass('fa-minus-circle fa-plus-circle');
});
});
$(function () {
$('.date-hide').click(function () {
$(this).find('i').toggleClass('fa-caret-down fa-caret-up');
});
});
function pullDetails(carrierId, startDate, status, divid) {
$.get("#Url.Action("getDelayedSpiffOrderDetails", "Dashboard")",
{ carrierId: carrierId, startDate: startDate, status: status },
function (data) {
$('.' + divid + ' .submitted_details').html(data);
$('.' + divid).removeClass('carrier-hide');
});
}
Try something like this
$("#startDate").change(function () {
// call your function here
});