In my App I have an $http.get() request that stores data into the array $scope.requirements and a boolean into $scope.requirementsFulfilled.
I have a directive using the same controller as the page. They both do an ng-repeat on the $scope.requirements. When the requirementsFulfilled is false only the directive version shows, when true only the containing page.
The problem is when I envoke $http.get() after the first time the results are only being stored in the directive version. How do I make sure this information is bound to both?
Within the controller...
$scope.requirementsFulfilled;
$scope.requirements = [];
$scope.getRequirements = function(url) {
$http.get(url)
.then(function(res){
$scope.requirements = res.data.requirements;
$scope.setFulfilled( res.data.fulfilled );
});
};
$scope.submitRequirementScan = function() {
if ($scope.checkRequirement() ) {
$scope.getRequirements('tempjson/requiredPartsFulfilled.json');
}
};
$scope.setFulfilled = function( inputFulfilled ) {
$scope.requirementsFulfilled = inputFulfilled;
};
$scope.getRequirements('tempjson/requiredParts.json');
The page gets the requirements and populates the page. Then the user takes actions which fires off checkRequirement() and then fetches the new json if true. From this point only the directive is updating.
I believe that a child scope is being created for the directive, but I am not certain exactly what is happening. Here is the entirity of the directive info.
.directive("operationRequirements", function () {
return {
restrict: "E",
templateUrl: "requirements/requirements.html"
};
});
What is going on with it?
edit - Html for the directive
<div class="col-md-6 col-md-offset-3">
<h5>Scan Requirements</h5>
<form ng-submit="submitRequirementScan()" ng-controller="operationCtrl">
<label> <div class="glyphicon glyphicon-barcode ng-hide" ng-hide="requirement.scanned"></div>
<input type="text" ng-model="text" name="text" placeholder="Scan Barcode" autofocus /></label>
<input type="submit" id="submit" value="Submit Scan" class="btn" />
<table class="table table-hover">
<tr ng-repeat="requirement in requirements | filter : unScannedFilter">
<td>{{$index + 1 }}</td>
<td>
<div class="glyphicon glyphicon-barcode ng-hide" ng-hide="requirement.scanned"></div>
<div class="glyphicon glyphicon-check ng-show" ng-show="requirement.scanned"></div>{{requirement.scanned}}
<div class="col-md-4">
<input type="checkbox" ng-model="requirement.scanned">
</div>
</td>
<td>{{requirement.partId}} - {{requirement.partDescription}}</td>
</tr>
</table>
</form>
</div>
edit 2 -- Html that invokes the directive operation-Requirements and the on page display of the requirements hidden with ng-show.
<div class="row" ng-hide="requirementsFulfilled" >
<operation-Requirements></operation-Requirements>
</div>
<div class="col-md-12" ng-show="requirementsFulfilled">
<table class="table table-hover">
<tr ng-repeat="requirement in requirements">
<td>{{$index + 1 }}</td>
<td>
<div class="glyphicon glyphicon-barcode ng-hide" ng-hide="requirement.scanned"></div>
<div class="glyphicon glyphicon-check ng-show" ng-show="requirement.scanned"></div>
</td>
<td>{{requirement.partId}} - {{requirement.partDescription}}</td>
</tr>
</table>
</div>
So maybe this will help point you in the right direction. What I've done is pulled out the requirements stuff into its own service. Now you have a singleton that handles everything that deals with parts. When its updated in one place its updated everywhere. The directive no longer needs that other controller.
http://plnkr.co/edit/Nej79OI3NrKcrkMNix3D?p=preview
app.service('partsService', function() {
return {
requirementsFulfilled: false,
requirements: [],
getRequirements: function () {
this.requirements.push({partId: 1, partDescription: 'Some Desc', scanned: false});
this.requirements.push({partId: 2, partDescription: 'Some Desc 2', scanned: true});
},
submitScan: function (id) {
this.requirements.filter(function (part) {
return part.partId === id;
}).map(function (part) {
part.scanned = true;
});
this.requirementsFulfilled = this.requirements.filter(function (part) { return !part.scanned }).length === 0;
}
};
});
Related
I have a form, when I submit it, it pushes some object to my array. Beneath that form I have a table that shows all items in that array. I want my table to update automatically (without refreshing the page) when new item pushed.
Submit button:
<button type="submit" class="btn btn-default" ng-click="updateTable()">Pay</button>
In my controller:
$scope.updateTable = function() {
setTimeout(function () {
$scope.$apply();
$scope.$digest();
}, 0);
};
However, it does not work.
I tried different approaches like $watch service, but i`ve got the same result.
Table
<div class="row paytable">
<div class="col-xs-10 col-xs-offset-1">
{{payments.length}}
<table class="table table-hover ">
<tr>
<td>Id</td>
<td>Amount</td>
<td>Cause</td>
</tr>
<tr ng-repeat="item in payments">
<td>{{item.id}}</td>
<td>{{item.amount}}</td>
<td>{{item.cause}}</td>
</tr>
</table>
</div>
</div>
Controller
app.controller('mainController', [ 'user', '$rootScope', '$scope', 'payment', '$timeout', function(user, $rootScope, $scope, payment, $timeout) {
user.getUsers();
user.newUser();
$rootScope.currentUser = user.currentUser();
$scope.payments = payment.getPayments();
$scope.newPayment = payment.newPayment;
$scope.updateTable = function() {
setTimeout(function () {
console.log('apply ------------');
$scope.$apply();
$scope.$digest();
}, 0);
};
$scope.showPayMessage = function() {
console.log('im here');
$scope.showSM = true;
$timeout(function() {
$scope.showSM = false;
}, 2000);
};
}]);
payment - my service for array manipulation.
Form
<div class="newpay row" >
<div class=" col-xs-10 col-xs-offset-1">
<h1>Hello, {{currentUser.name}}</h1>
<h4 ng-show="showSM" class="bg-success">Payment confirmed</h4>
<form name="inputform" ng-submit="newPayment(amount, cause); showPayMessage();">
<div class="form-group">
<label for="exampleInputEmail1">Amount</label>
<input type="number" name="amount" ng-model="amount" class="form-control" id="exampleInputEmail1" placeholder="Amount" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Cause</label>
<input type="text" name="cause" ng-model="cause" class="form-control" id="exampleInputPassword1" placeholder="Cause" required>
</div>
<button type="submit" class="btn btn-default" ng-click="updateTable()">Pay</button>
</form>
</div>
</div>
payments: {{payments.length}}
<payments-table payments="payments"></payments-table>
To display that table I created directive.
$scope.$apply and $scope.$digest are better suited for working with 3rd party libraries or testing. In your case Angular is well aware to your changes. The thing is, your payments array, that resides in a service should be queried again after submitting a new item (unless you have a direct reference to the array, then no query should be made).
Like this:
View
<form name="inputform" ng-submit="onSubmit()">
Controller
$scope.onSubmit = function() {
newPayment($scope.newItemAmount, $scope.newItemCause); // Assuming they are properties in the controller
showPayMessage();
$scope.payments = payment.getPayments(); // getting the updated array
}
I suspect what I'm trying to do is very simple, I'm new to Angular so some obvious practices sort of go over my head. I'm having trouble accessing the show view (sorry, I'm coming to angular from Rails, so I still think in those terms a little bit) for my Acts resource. The view renders fine, but it isn't displaying the data I would like. I suspect the template isn't receiving the $scope.act variable I'm defining in the controller. When I use console.log in the controller, I can see that the variable contains all the data I want to use. I assume I have to do something to pass the variable as a parameter to the template, but I'm not sure how I'd do that.
Here's my code:
app.js
$(document).on('page:load', function() {
return $('[ng-app]').each(function() {
var module;
module = $(this).attr('ng-app');
return angular.bootstrap(this, [module]);
});
});
var snowball_effect = angular.module('snowball_effect', [
'templates',
'ngRoute',
'ngResource',
'controllers'
]);
snowball_effect.config([
'$routeProvider', function($routeProvider) {
return $routeProvider
.when('/', {
templateUrl: "static_pages/templates/index.html",
controller: 'StaticPagesController'
})
.when('/acts/index', {
templateUrl: "acts/templates/index.html",
controller: 'ActsController'
})
.when('/acts/:id', {
templateUrl: "acts/templates/show.html",
controller: 'ActsController'
});
}
]);
var controllers = angular.module('controllers', []);
ActsController.js
controllers = angular.module('controllers');
controllers.controller('ActsController', [
'$scope',
'$routeParams',
'$location',
'$resource',
function($scope,$routeParams,$location,$resource) {
var Act = $resource('/acts/:actId', {
actId: "#id",
format: 'json'
}, {
'create': {
method: 'POST'
}
});
$scope.acts = Act.query();
$scope.addAct = function() {
act = Act.save($scope.newAct, function() {
$scope.acts.push(act);
$scope.newAct = '';
});
}
$scope.deleteAct = function(act) {
Act.delete(act);
$scope.acts.splice($scope.acts.indexOf(act), 1);
}
$scope.linkToShowAct = function(act) {
$scope.act = act;
console.log($scope.act);
$location.path('acts/' + act.id);
}
}]);
show.html
<div class="acts-show">
<div class="container" ng-controller="ActsController">
<div class="body">
<h1>
{{act.name}}
</h1>
<p class="act-show-description">
{{act.description}}
</p>
<p class="act-show-inspires">
<strong>Inspires:</strong>
{{act.inspires}}
</p>
Edit
Back
</div>
</div>
</div>
index.html
<div class="actions_body">
<div class="container">
<h2>Listing Actions</h2>
<div ng-controller="ActsController" class="body">
<table class="row">
<thead>
<tr>
<th class="col-md-2 col-md-offset-1 active">
<label>Name</label>
</th>
<th class="col-md-4">Description</th>
<th class="col-md-2">Inspires</th>
<th colspan="2" class="col-md-2">Modify</th>
</tr>
</thead>
<tbody ng-repeat="act in acts">
<td class="col-md-offset-1 col-md-2">{{act.name}}</td>
<td class="col-md-4">{{act.description}}</td>
<td class="col-md-2">{{act.inspires}}</td>
<td>Edit</td>
<td><button ng-click="deleteAct(act)">Delete</a></button>
</tbody>
</table>
<br>
<button ng-click="newActShow=true">New Action</button>
<button ng-click="newActShow=false">Hide</button>
<div ng-show="newActShow" id="newAct">
<div class="row">
<form class="form-inline" ng-submit="addAct()">
<div class="col-md-3 form-group">
<label for="newActname">Name</label>
<input type="text" ng-model="newAct.name" id="newActname" placeholder="Name" class="form-control col-md-2">
</div>
<div class="col-md-3 form-group">
<label for="newActdescription">Description</label>
<input type="textarea" ng-model="newAct.description" id="newActdescription" placeholder="Description" class="form-control col-md-2">
</div>
<div class="col-md-3 form-group">
<label for="newActinspires">Inspires</label>
<input type="number" ng-model="newAct.inspires" id="newActinspires" placeholder="Inspires" class="form-control col-md-2">
</div>
<div class="col-md-3 form-group">
<input type="submit" value="+" class="btn btn-success">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
try $locationChangeStart in order to make sure your value is set to the scope variable before the state actually changes and the route happens, even if you put the $location.path('acts/' + act.id); before setting the variable, there is no guarantee that the value will be set before the state change (the actual routing).
I would prefer (a more safe value setting method) using a promise for example ..
I have quite interesting and disturbing problem to solve. I am working on project using MVVM Kendo UI pattern and I have issue with data-bind: checked for radio buttons.
When I bind some variable from VM to view using data-bind, it is binded successfully for all radio buttons except the very last one. So whenever I change radio value to the last one - variable in VM is not changed and therefore no attached listeners to this variable are called.
HTML view:
<div data-role="modalview"
class="dialogStyle width60em"
data-hide="kitkat.widgets.zivotniPojisteniDialog.hide"
data-model="kitkat.widgets.zivotniPojisteniDialog"
data-init="kitkat.widgets.zivotniPojisteniDialog.init">
<div class="dialogContainer kitkat-switches">
<form id="form">
<div data-role="scroller" class="scroller">
<div class="row">
<span data-bind="source: nameSource" data-template="name-tmpl"></span>
<script type="text/x-kendo-template" id="name-tmpl">
<input type="radio" name="firstname" value="#= idx#" data-bind="checked: nameSelectedValue"
id="firstname#= idx#" />
<label class="black" for="firstname#= idx#">#= name#</label>
</script>
</div>
<div id="tables">
<!-- example tables, originally created by nested external templates -->
<table id="table0" data-bind="visible: firstnameChanged">
<tr class="row">
<td class="firstColumn"></td>
<td class="secondColumn"></td>
<td class="thirdColumn"></td>
</tr>
</table>
<table id="table1" data-bind="visible: firstnameChanged">
<tr class="row">
<td class="firstColumn"></td>
<td class="secondColumn"></td>
<td class="thirdColumn"></td>
</tr>
</table>
<!-- - - - - - - -->
</div>
</div>
</form>
</div>
</div>
JS viewmodel:
<script>
var _dialog = kendo.observable({
// hardcoded data for this example
nameSource: [
{
"idx" : 0,
"name" : "John"
},
{
"idx" : 1,
"name" : "George"
}
],
nameSelectedValue: null, // problematic variable
init: function(e) {
var self = _dialog;
self._view = e.sender;
self._view.shim.popup.options.animation.open.effects = "slideIn:down";
$(self._view.element).closest('.km-shim').addClass('dialogs-shim');
self.initView("form");
self.bind("closed", function() {self.hide();});
},
show: function(jeProDeti) {
var self = _dialog;
self._view.open();
},
hide: function() {
},
cancel: function() {
kitkat.touch( function() {
var self = _dialog;
self.trigger('done');
self._view.close();
self.trigger('closed');
});
},
firstnameChanged: function(e) {
var self = _dialog;
var idx = e.idx;
var selectedIdx = parseInt(self.get("nameSelectedValue")); // getter for registering "nameSelectedValue" change
if(idx === selectedIdx) { // table is visible if corresponding radio value is selected
return true;
}
return false; // otherwise it is invisible
}
});
</script>
Thank you for any advice
Ok the problem was kind of weird for me. I wrapped every radio input into its own <span> and it worked
I am trying to take some JSON and fill the options of dropdown menu.I am using Materialize a front end css framework which I think may be the root of the problem here. I say this because if I do it with the default browser dropdown it works exactly as I expect, but not with their (Materialize's) dropdown. I do have to init the dropdown when the page loads, so maybe the solution is I have to re-init it, but I do not know how to do that.
This is the html where the form is:
<div class="row" style="margin-bottom:0px">
<form class="col s12"> <div class="row">
<div class="input-field col s12">
<select ng-options="Country for Country in countries" ng-model="selCountry" ng-change="onChange('sel')">
<option value="" disabled>Select Indicator</option>
</select>
<label>Indicators</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="search_targets" type="text" ng-model="searchText" ng-change="onChange('txt')">
<label for="search_targets">Search Targets</label>
</div>
</div>
<div class="col s12" style="
padding-left: 11.250px;
padding-right: 11.250px;
margin top:5vh;
">
<table>
<thead>
<tr>
<th data-field="id">Name</th>
<th data-field="name">Score</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="item in records | orderBy:'Name':reverse | filter:selCountry | filter:searchText | limitTo: 10">
<td>{{item.Name}}</td>
<td>{{item.Country}}</td>
</tr>
</tbody>
</table>
</div>
</form>
</div>
This is all of the JS I have, including the initialization of the dropdown # the bottom:
(function($){
angular.module('myapp', [])
.controller('MainCtrl', function($scope, $http) {
var records;
$scope.selCountry = '';
$scope.searchText = '';
$http.get('http://www.w3schools.com/angular/customers.php').success(function(dt) {
//window.alert(angular.toJson(dt));
$scope.countries = [];
$scope.records = dt.records;
dt.records.forEach(function(o) {
var c = o.Country;
if ($scope.countries.indexOf(c) == -1)
$scope.countries.push(c);
});
$scope.total = $scope.countries.length;
ready();
});
$scope.matches = 0;
$scope.onChange = function(src) {
if (src === 'txt') {
$scope.selCountry = '';
$scope.search = $scope.searchText;
} else {
$scope.searchText = '';
$scope.search = $scope.selCountry;
}
search($scope.search);
};
});
$(function(){
$('.button-collapse').sideNav();
}); // end of document ready
$('.datepicker').pickadate({
selectMonths: true, // Creates a dropdown to control month
selectYears: 15 // Creates a dropdown of 15 years to control year
});
$(document).ready(function(){
$('ul.tabs').tabs('select_tab', 'tab_id');
$('select').material_select();
});
})(jQuery); // end of jQuery name space
If the solution is to re-initialize the dropdown after the JSON is pulled, I am not sure how to do so.
In the success callback, you must use $scope.$apply to apply scope modifications since $http is asynchronous. Then did you check what dt contains with console.log(dt)?
You can reinitialize or update your select element by simply calling (as the same way you init)
$('select').material_select();
Note: You should call this statement on your success callback.
I have a table and in of it's column I want user when click on button that is inside this column pop up window appear which have checkboxes and after user checked checkbox it will be appear as output in same column which were have a button as well as post these values of selected checkboxes and user name to database (PHP). I'm a beginner and i wish anyone help me.
help.html code :
<html>
<head>
<SCRIPT LANGUAGE="JavaScript">
myPopup = '';
function openPopup(url) {
myPopup = window.open(url,'popupWindow','width=640,height=480');
if (!myPopup.opener)
myPopup.opener = self;
}
</SCRIPT>
</script>
</head>
<body>
<table border="1">
<tr>
<th> user name </th>
<th>product selected</th>
</tr>
<tr>
<td> <input type="text"/></td>
<td> <button onclick="openPopup('f.html')">select</button></td>
</body>
</html>
And this my f.html code:
<HTML>
<HEAD>
</HEAD>
<BODY>
<FORM NAME="popupForm">
<INPUT TYPE="checkbox" >Cell phone</br>
<INPUT TYPE="checkbox" >TV</br>
<INPUT TYPE="checkbox" >Book</br>
<INPUT TYPE="BUTTON" VALUE="Submit">
</FORM>
</BODY>
With AngularJS you would do it like this:
Get the data from server with an ajax request. In the demo I've used static data to reduce complexity.
Create a ng-repeat to create the table
Add the selected data that is stored in an array into the table cell.
Make the list clickable by adding ng-click that opens a bootstrap modal to the table cell or wrap the selected data in a button.
In the modal create a form with ng-repeat with your selected products. Testing if the current item is clicked can be done with array.indexOf(item) !== -1 that returns true if the item is in the array.
With every click to the checkboxes update the product array.
After OK button click, close modal and post the updated data to the server with an ajax request. (A check if the data have changed would be good.)
You could also do it with-out AngularJS but I think there you would have to do a lot more code to get that behaviour.
(I'm also pretty new to javascript and AngularJS, so the code is not perfect, but it works.)
There are probably somethings that could be improved e.g. work with services to do the ajax requests.
There is one bug in the script:
The cancel click is not working as expected. The data will be changed even with cancel click.
You can fix this by working with a copy of the scope data or restore the original data if cancel is clicked.
DEMO
Please find the demo below (it is not working here because it seems that bootstrap.ui uses cookies that are not allowed at SO) and here at jsFiddle. Check it at jsFiddle. There it works.
var app = angular.module('myApp', ['ui.bootstrap']);
app.controller('mainController', function($scope, $modal, $log) {
$scope.products = ['coffee', 'beer', 'wine', 'tea', 'milk'];
// userData will be later from server with $http.get('/phpscript').success(...)
// just dummy userData here because no backend available
$scope.userData = [
{
name: 'John Doe',
selectedProducts: [
'coffee',
'beer',
'wine']
},
{
name: 'Jane Doe',
selectedProducts: [
'coffee',
'tea']
}
];
$scope.changeProducts = function(userData) {
//$scope.items = ['item1', 'item2', 'item3'];
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
//size: size,
resolve: {
user: function() {
return userData;
},
selectedProducts: function() {
return userData.selectedProducts;
},
products: function () {
//console.log($scope.selectedProducts);
return $scope.products; // get all available products
}
}
});
modalInstance.result.then(function (selectedItems) {
//products = selectedItems;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
});
app.controller('ModalInstanceCtrl', function ($scope, $http, $modalInstance, products, selectedProducts, user) {
//console.log('user', user);
$scope.products = products;
$scope.selected = selectedProducts;
$scope.chkChange = function(item) {
console.log(item);
var index = $scope.selected.indexOf(item);
if (index > -1) {
$scope.selected.splice(index, 1);
}
else {
// not selected --> we have to add it
$scope.selected.push(item);
}
console.log($scope.selected);
};
//console.log(selectedProducts);
$scope.ok = function () {
// prepare everything for sending to sever
// --> probably check here if the data have changed or not (not implemented yet)
console.log('new selection', $scope.selected);
var data = $.param({
json: JSON.stringify({
user: user.name,
products: $scope.selected
})
});
$http.post('/echo/json/', data)
.success(function(data, status) {
console.log('posted the following data:', data);
});
$modalInstance.close();//); $scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
//custom filter to display the selected products.
app.filter('array', function() {
return function(input) {
//console.log(input);
return input.join(', ');
};
});
body {
padding: 5px;
}
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.1.js"></script>
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<div ng-app="myApp">
<div ng-controller="mainController">
<script type="text/ng-template" id="myModalContent.html">
<!-- template for modal -->
<div class="modal-header">
<h3 class="modal-title">Choose your products!</h3>
</div>
<div class="modal-body">
<form>
<div class="checkbox" ng-repeat="item in products">
<label>
<input type="checkbox" ng-click="chkChange(item)" ng-checked="selected.indexOf(item) !== -1"/>
{{item}}
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
<table class="table">
<tr>
<th>User name</th>
<th>products selected</th>
</tr>
<tr ng-repeat="user in userData">
<td>{{user.name}}</td>
<td><button ng-click="changeProducts(user)">{{( user.selectedProducts | array ) || 'nothing selected!' }}</button></td>
</tr>
</table>
</div>
</div>
This snippet will pop up the box. And the submit will submit everything. I do not think this is what you want. I am guess there will be more products.
Select opens popup
Submit submits to product.php
function openPopup(){
var pop = document.getElementById('pop').style.display='block';
}
#pop{
font:400 1em Arial,sans-serif;
width:20em;
display:none;
position:absolute;
top:0;left:0;
background:#ff0;
color:#000;
height:8em;
z-index:10;
}
#frm{width:100%;}
<FORM id="frm" action="product.php" method="post"><div>
<div id="pop">
<INPUT TYPE="checkbox" >Cell phone</br>
<INPUT TYPE="checkbox" >TV</br>
<INPUT TYPE="checkbox" >Book</br>
<INPUT TYPE="submit" VALUE="Submit">
</div>
</div>
<table border="1">
<tr><th> user name </th><th>product selected</th></tr>
<tr><td> <input type="text"/></td>
<td> <button type="button" onclick="openPopup()">Select</button></td>
</tr></table>
</form>
This snippet will pop up the box. you could get the check box values with JS but I think it would be better to submit to a PHP script at this point. but only you know this. I am now working on submitting everything to a script.
Select opens popup
Submit closes popup
function openPopup(){
var pop = document.getElementById('pop').style.display='block';
}
function closePopup(){
var pop = document.getElementById('pop').style.display='none';
}
#pop{
font:400 1em Arial,sans-serif;
width:20em;
display:none;
position:absolute;
top:0;left:0;
background:#ff0;
color:#000;
height:8em;
z-index:10;
}
#frm{width:100%;}
<div id="pop">
<FORM id="frm" NAME="popupForm"><div>
<INPUT TYPE="checkbox" >Cell phone</br>
<INPUT TYPE="checkbox" >TV</br>
<INPUT TYPE="checkbox" >Book</br>
<INPUT TYPE="BUTTON" VALUE="Submit"onclick="closePopup()">
</div></FORM>
</div>
<table border="1">
<tr>
<th> user name </th>
<th>product selected</th>
</tr>
<tr>
<td> <input type="text"/></td>
<td> <button onclick="openPopup()">select</button></td>