I am showing a modal popup on click of a button in a row in ng grid.So to get a form in the modal popup i am filling it with JSON Schema as follows
The Html Of Modal Pop Up is
<div class="modal-header">
<h3 class="modal-title">Edit Row</h3>
</div>
<div class="modal-body">
<form sf-schema="schema" sf-form="form" sf-model="entity"></form>
</div>
<div class="modal-footer">
<button class="btn btn-success" ng-click="save()">Save</button>
<button class="btn btn-warning" ng-click="$close()">Cancel</button>
</div>
</div>
The schema is put into the constant like below in an external js file:
var app = angular.module("myApp", ['ngGrid','ui.bootstrap']);
app.constant('UserPopUpSchema', {
type: 'object',
properties: {
FullName: { type: 'string', title: 'FullName' },
UserName: { type: 'string', title: 'UserName' },
Password: { type: 'string', title: 'Password' },
EmailAddress: { type: 'string', title: 'EmailId' },
Phone: {type:'string',title:'phNum'}
}
});
So on click of a row in ng-grid I am executing a function called edit row ,which would open the pop up and fill the form according to the constant.
$scope.editRow = function (grid,row) {
$modal.open({
templateUrl: 'PopUpTemplate.htm',
controller:['$modalInstance', 'grid', 'row','UserPopUpSchema', function($modalInstance,grid,row){
schema = 'UserPopUpSchema';
entity = angular.copy(row.entity);
form = [
'FullName',
'UserName',
'Password',
'EmailId',
'phNum'
];
}],
resolve: {
grid: function () { return grid; },
row: function () { return row; }
}
});
};
But here I am a bit confused on how to inject a constant to a controller function .As a result the modal appear with a blank form.
Appreciate any help!!
Try this
$modal.open({
templateUrl: 'PopUpTemplate.htm',
controller: function ($modalInstance, grid, row, UserPopUpSchema) {
// Do Stuff
},
resolve: {
grid: function () {
return grid;
},
row: function () {
return row;
},
UserPopUpSchema: function () {
return UserPopUpSchema;
}
}
});
app.controller('Myctrl',function($scope,UserPopUpSchema) {
$scope.editRow = function (grid,row) {
$modal.open({
templateUrl: 'PopUpTemplate.htm',
controller:['$modalInstance', 'grid', 'row','UserPopUpSchema', function($modalInstance,grid,row){
schema = 'UserPopUpSchema';
entity = angular.copy(row.entity);
form = [
'FullName',
'UserName',
'Password',
'EmailId',
'phNum'
];
}],
resolve: {
grid: function () { return grid; },
row: function () { return row; }
UserPopUpSchema: function () { return UserPopUpSchema; }
}
});
};
});
and in the modal instance controller inject the UserPopUpSchema along with grid and row
$modal.open() accept a "resolve" property in which you can pass all the data you want.
$modal.open({
templateUrl: 'templateUrl',
controller: 'controllerName',
resolve: {
data: function(){
// Here, return a JSON object containing all the data you want to pass to the controller.
}
}
});
Then your controller will look like this :
yourApp.controller('controllerName', function ( $scope, $modalInstance, data ){
// Here, using data, you can access the JSON object you passed previously.
});
Related
How can I get the value of a string in ui-grid angular selection and pass it to the Spring controller.
I tried everything, it doesn’t work.
My JS file:
var app = angular.module('app', ['ui.grid', 'ui.grid.pagination', 'ui.grid.selection', 'ui.grid.cellNav']);
app.controller(
'StudentCtrl', ['$scope', 'StudentService', '$http',
function ($scope, StudentService) {
var paginationOptions = {
pageNumber: 1,
pageSize: 5,
sort: null
};
StudentService.getStudents(
paginationOptions.pageNumber,
paginationOptions.pageSize).success(function (data) {
$scope.gridOptions.data = data.content;
});
$scope.gridOptions = {
paginationPageSizes: [5, 10, 20],
paginationPageSize: paginationOptions.pageSize,
enableColumnMenus: false,
useExternalPagination: true,
columnDefs: [
{
name: 'id',
field: 'id',
},
{
name: 'productName',
field: 'productName'
},
{
name: 'price',
field: 'price'
},
],
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
gridApi.pagination.on.paginationChanged(
$scope,
function (newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
StudentService.getStudents(newPage, pageSize)
.success(function (data) {
$scope.gridOptions.data = data.content;
});
});
}
};
}
]
);
app.service('StudentService', ['$http', function ($http) {
function getStudents(pageNumber, size) {
pageNumber = pageNumber > 0 ? pageNumber - 1 : 0;
return $http({
method: 'GET',
url: 'student/get?page=' + pageNumber + '&size=' + size
});
}
return {
getStudents: getStudents
};
}]);
My controller Spring
#PostMapping
public String placeYourOrder(Order order, Model model,
#AuthenticationPrincipal User user,
Map<String, Object> orderNumberModel,
#RequestParam(value="productName")String productName) {
orderService.saveOrder(order, user, productName);
List<Order> orders = orderRepository.findAll();
List<Order> orderNumberByUserName = orderRepository.findOrderNumberByUserName(user.getUsername());
model.addAttribute("orders", orders);
if (Component.isUser()) {
orderNumberModel.put("orderNumber", orderNumberByUserName);
return "orderNumber";
} else return "orderList";
}
}
I need to pass to the #RequestParam parameter, which forms an order based on the goods in the table.
Write template for the 'productName' column. Since you haven't mentioned when the 'http call' is made I assume its called on Click of 'productName' on each row.
Refer this url
http://ui-grid.info/docs/#!/tutorial/Tutorial:%20317%20Custom%20Templates
If your cell template is as below
{ field: 'click', cellTemplate: '<div class="btn primary" ng-click="grid.appScope.placeYourOrder(row)"><span ng-bind="row.entity.productName"></span></div>' }
Alternatively you can choose to write row-template if you want to call the service if clicked anywhere in a row.
You can pass the entire row to the method, get only the required fields, form the request and call the service.
Refer this url to pass RequestParam
AngularJS Spring mvc #RequestParam
Hope this helps.
I want to give two option to user by the popup and after selection I go for the same page, but if some diferences.
mapsWazePopup = function () {
var importPopup = $ionicPopup.show({
title: "Selecione uma das opcoes:",
scope: $scope,
cssClass: "popup-import",
buttons: [
{
text: '<b>Maps</b>',
type: 'button button-positive',
onTap: function () {
$location.path("/Home");
}
},
{
text: '<b>Waze</b>',
type: 'button button-positive',
onTap: function () {
$location.path("/Home");
}
},
]
});
}
and the routes.
angular.module("routes", [])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('index', {
url: '/',
templateUrl: 'index.html',
controller: 'ionicApp'
})
.state('mapa', {
url: '/mapa',
templateUrl: 'templates/mapa.html',
controller: 'mapaCtrl'
});
});
But nothing happen :( I created a .js file just for the routes. I want just to go for this page.
To navigate in angular you have to use $state service instead of $location:
$state.go('home');
//or
$state.go('mapa');
The parameter is the state's name instead of the url.
The onTap function returns a promise, so you will want to do something like this instead where you return the path of the button pressed:
angular.module('mySuperApp', ['ionic'])
.controller('PopupCtrl', function ($scope, $ionicPopup, $state) {
$scope.mapsWazePopup = function () {
var importPopup = $ionicPopup.show({
title: "Selecione uma das opcoes:",
scope: $scope,
cssClass: "popup-import",
buttons: [
{
text: '<b>Maps</b>',
type: 'button button-positive',
onTap: function (e) {
//To do nothing on button press -> e.preventDefault();
return ('mapa');
}
},
{
text: '<b>Waze</b>',
type: 'button button-positive',
onTap: function (e) {
//To do nothing on button press -> e.preventDefault();
return ('Home');
}
},
]
});
importPopup.then(function (res) {
//res is your response from the promise,
//which will be the path depending on which button was pressed
console.log('Path: ', res);
$state.go(res)
});
};
});
However, in your routes file you have no path to /Home.
Use $state not location, more info on it here. You can read more on ionicPopup here, and a codepen of ionics nightly with this type of functionality for you to play around with.
I'm building an Angular pop-up system for multiple purposes. The way it works is that I have a directive called bitPopup which three variables get passed on to (type, action and data) as shown below:
index.html
<bit-popup type="popup.type" action="popup.action" data="popup.data"></bit-popup>
popup.js
app.directive('bitPopup', function () {
return {
restrict: 'E',
template: html,
scope: {
type: '=',
action: '=',
data: '='
},
[***]
}
}
The popup controller then loads a different directive based on the type:
popup.html (The HTML template shown above)
<div class="pop-up" ng-class="{visible: visible}" ng-switch="type">
<bit-false-positive-popup ng-switch-when="falsePositive" type="type" action="action" data="data"></bit-false-positive-popup>
</div>
false_positives.js (Containing the bitFalsePositivePopup directive)
[...]
scope: {
type: '=',
action: '=',
data: '='
}
[...]
And then the html template for the bitFalsePositivePopup directive displays some properties from data.
Now the way I'm triggering a pop-up works like this:
From a template inside a directive containing the bitPopup directive i'll change $scope.popup's type, action and data.
I'll do $scope.$broadcast('showPopup');
The bitPopup directive will react because of $scope.$on('showPopup', [...]}); and makes the pop-up visible.
Now this really weird thing occurs where it works on the first try (the pop-up opens with the correct data information), but after the first try it will display the data from the previous try.
Now what's even weirder is that I tried logging the information on the first try and what I found out is that:
$scope.popup at index.html just before calling $scope.$broadcast('showPopup'); displays the right information.
$scope.data at the bitPopup directive displays null
$scope.data at the bitFalsePositivePopup directive displays the right information.
On the second try:
$scope.popup at index.html is correct again.
$scope.data at the bitPopup directive displays the information from the previous attempt
The same holds for the bitFalsePositivePopup directive.
Another weird thing is that when I use $scope.$apply() it does work correctly, only it displays the $apply already in progress error. I know I shouldn't use $scope.$apply() in this case, because it's all Angular events. But how is it possible that the passed scope is always a step behind?
Am I doing something wrong to begin with?
EDIT:
Because of amahfouz's answer I decided to post some more code for clarification. I left out some unimportant details for more clear reading.
index.html
<div class="falsePositives" ng-controller="falsePositives">
<i class="fa fa-minus color-red" ng-click="triggerPopup('falsePositive', 'delete', {detection: getDetection(row.detection, row.source), source: row.source, triggers: row.triggers, hash: row.hash, date: row.date})"></i>
<i class="fa fa-pencil" ng-click="triggerPopup('falsePositive', 'edit', {detection: getDetection(row.detection, row.source), source: row.source, triggers: row.triggers, hash: row.hash, date: row.date})"></i>
<bit-popup type="popup.type" action="popup.action" data="popup.data"></bit-popup>
</div>
index.js
var app = require('ui/modules').get('apps/falsePositives');
app.controller('falsePositives', function ($scope, $http, keyTools, bitbrainTools, stringTools) {
function init() {
$scope.getDetection = getDetection;
$scope.popup = {
type: null,
action: null,
data: null
};
}
function getDetection(hash, source) {
return {
'ids': 'BitSensor/HTTP/CSRF',
'name': 'CSRF Detection',
'description': 'Cross domain POST, usually CSRF attack',
'type': [
'csrf'
],
'severity': 1,
'certainty': 1,
'successful': false,
'input': ['s'],
'errors': []
};
}
$scope.triggerPopup = function (type, action, data) {
$scope.popup = {
type: angular.copy(type),
action: angular.copy(action),
data: angular.copy(data)
};
test();
$scope.$broadcast('showPopup');
};
function test() {
console.log('$scope.popup: ', $scope.popup);
}
}
popup.html
<div class="pop-up-back" ng-click="hidePopup()" ng-class="{visible: visible}"></div>
<div class="pop-up" ng-class="{visible: visible}" ng-switch="type">
<bit-false-positive-popup ng-switch-when="falsePositive" type="type" action="action" data="data"></bit-false-positive-popup>
</div>
popup.js
var app = require('ui/modules').get('apps/bitsensor/popup');
app.directive('bitPopup', function () {
return {
restrict: 'E',
template: html,
scope: {
type: '=',
action: '=',
data: '='
},
controller: function ($scope) {
$scope.visible = false;
$scope.$on('showPopup', function () {
console.log('$scope.data: ', $scope.data);
$scope.visible = true;
});
$scope.$on('hidePopup', function () {
hidePopup();
});
function hidePopup() {
$scope.visible = false;
}
$scope.hidePopup = hidePopup;
}
};
});
false_positives.js
var app = require('ui/modules').get('apps/bitsensor/falsePositives');
app.directive('bitFalsePositivePopup', function () {
return {
restrict: 'E',
template: html,
scope: {
type: '=',
action: '=',
data: '='
},
controller: function ($scope, objectTools, bitbrainTools, keyTools) {
function init() {
console.log('$scope.data # fp: ', $scope.data);
}
function hidePopup() {
$scope.data = null;
$scope.$emit('hidePopup');
}
$scope.$on('showPopup', function () {
init();
});
init();
$scope.hidePopup = hidePopup;
}
}
}
Without the rest of the code I can only guess: You either need to use a promise when displaying the popup or use the $apply service to make the change to the popup visibility.
surround your $broadcast event in $timeout like follow:
$timeout(function() {
$broadcast('eventName');
});
It will wait for $scope update and then will trigger the event.
I am new in angularJs and I have an application that using angular modal and jqGrid. (I know that this is not good. But for some reason I must work with two, now.)
My modal content loads with a templateUrl.
<div ng-controller="SearchPerson as ctrl">
<div class="modal-body">
<table id="list"></table>
<div id="pager"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-link" data-dismiss="modal" ng-click="$close()">CLOSE</button>
<button type="button" class="btn btn-primary" ng-click="ctrl.CLOSE()">Save changes</button>
</div>
</div>
and for create I have this code:
$(function () {
$("#list").jqGrid({
url: "/Home/List",
datatype: "json",
mtype: 'GET',
colNames: [" ", "FirstName", "LastName"],
colModel: [
{
width: 30,
sortable: false,
formatter: function (cellvalue, options, rowObject) {
return 'SELECT';
},
},
{
name: "FirstName",
width: 60,
},
{
name: "LastName",
width: 90
}
],
jsonReader: {
page: "Page",
total: "Total",
records: "Records",
root: "Rows",
repeatitems: false,
cell: "cell",
id: "id",
userdata: "userdata",
},
pager: "#pager",
});
});
and for open modal I write this code:
angular.module('AngularModal', ['ui.bootstrap']);
angular.module('AngularModal').controller('ModalDemoCtrl', function ($scope, $modal) {
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: '/Home/SearchGrid',
controller: 'ModalInstanceCtrl',
size: size,
backdrop: 'static',
});
modalInstance.result.then(function () {
//
}, function () {
//
});
};
});
angular.module('AngularModal').controller('ModalInstanceCtrl', function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
angular.module('AngularModal').controller('SearchPerson', function ($http, $modalStack) {
});
What I want is: when I click SELECT link in my grid, alert FirstName and then close the modal.
How to do this?
It is noteworthy that when I click CLOSE button, modal close. And also when I click "Save changes" buton, the modal will close.
But when I click SELECT link, modal does not close. While I write both ng-click of SELECT and "Save Change" for it.
Your code would definitely not work. For ng-click, the context of the expression is the current $scope, while for href="javascript:expression" the context is the global, or saying window.
For your situation, I would definitely suggest you try some other grid libraries which are more compatible with AngularJS (like http://angular-ui.github.io/ng-grid/ or http://ui-grid.info/). That may save tons of time.
Otherwise, if you really really insist on using jqGrid, you may need to wrap it into a directive manually by yourself. In your application, you may need to consider how to "angularize" the html snippet generated for the formatter function.
formatter: function (cellvalue, options, rowObject) {
var html = '<a ng-click="ctrl.Select()">SELECT</a>';
var linkFunc = $compile(html);
linkFunc(scope); // the scope in which you have the `ctrl.Select()` function.
return html;
},
$compile: https://docs.angularjs.org/api/ng/service/$compile
Then you will be able to call angular scope functions.
However, in my opinion, this is not a good practice. If any possible, find a replacement library, please.
Using this angular modal service:
app.service('modalService', ['$modal',
function ($modal) {
var modalDefaults = {
backdrop: true,
keyboard: true,
modalFade: true,
templateUrl: '/templates/modal.html'
};
var modalOptions = {
closeButtonText: 'Close',
actionButtonText: 'OK',
headerText: 'Proceed?',
bodyText: 'Perform this action?'
};
this.showModal = function (customModalDefaults, customModalOptions) {
if (!customModalDefaults) customModalDefaults = {};
customModalDefaults.backdrop = 'static';
return this.show(customModalDefaults, customModalOptions);
};
this.show = function (customModalDefaults, customModalOptions) {
//Create temp objects to work with since we're in a singleton service
var tempModalDefaults = {};
var tempModalOptions = {};
//Map angular-ui modal custom defaults to modal defaults defined in service
angular.extend(tempModalDefaults, modalDefaults, customModalDefaults);
//Map modal.html $scope custom properties to defaults defined in service
angular.extend(tempModalOptions, modalOptions, customModalOptions);
if (!tempModalDefaults.controller) {
tempModalDefaults.controller = function ($scope, $modalInstance) {
$scope.modalOptions = tempModalOptions;
$scope.modalOptions.ok = function (result) {
$modalInstance.close(result);
};
$scope.modalOptions.close = function () {
$modalInstance.dismiss('cancel');
};
}
}
return $modal.open(tempModalDefaults).result;
};
}]);
I'm having trouble understanding how to pass values from the modal (which has an input) to the controller.
This is my modal:
<input type="text" class="form-control" id="{{modalOptions.inputName}}" name="{{modalOptions.inputName}}" data-ng-model="modalOptions.inputVal" data-ng-if="modalOptions.inputName" />
<button type="button" class="btn"
data-ng-click="modalOptions.close()">{{modalOptions.closeButtonText}}</button>
<button class="btn btn-primary"
data-ng-click="modalOptions.ok();">{{modalOptions.actionButtonText}}</button>
Controller:
$scope.addTopic = function () {
var modalOptions = {
closeButtonText: 'Cancel',
actionButtonText: 'Create Topic',
inputName: 'topicName'
};
modalService.showModal({}, modalOptions).then(function (result) {
// I tried...
var input = $scope.inputName; // and...
input = result;
$log.log("Adding topic '" + input + "' to publication no " + $scope.publication.id);
});
}
So the input is an option in modalOptions but when the user enters a value and clicks ok, nothing is sent to the controller. $scope.inputName returns undefined and so does result.
Ideally, I want to end up with an object like so { inputs : {name: 'inputName' , value: 'abcde'} }.
Try the resolve method in Angular UI Bootstrap
var modalOptions = {
resolve: {
myvar: function () {
return $scope.myvar;
}
}
};
modalService.showModal(modalOptions);