How to pass data from the Server side to Bootstrap Modal in the AngularJS Directive

Hoa Do
Kilo Guru

Hello everyone, 

I am having trouble about passing data from the Server side to Bootstrap Modal in the AngularJS Directive. The data in the modal is not the same as that in the card. I check the console.log() in the browser, but it seems fine. Can you help me solve the problem? Thank you so much!

Some images:

find_real_file.png

find_real_file.png

find_real_file.png

Script Include (named "Incident_Utils"):

var Incident_Utils = Class.create();
Incident_Utils.prototype = {
  getAllIncident: function (input, currentPage, maxSize) {
    var incArr = [];
    var incidentGR = new GlideRecord("incident");
    incidentGR.addEncodedQuery("active=true");
    if (input) {
      var stringQuery =
        "short_descriptionLIKE" + input + "^ORnumberLIKE" + input;
      // console.log(stringQuery);
      incidentGR.addEncodedQuery(stringQuery);
    }
    incidentGR.chooseWindow(0, currentPage * maxSize);
    incidentGR.query();
    record_count = incidentGR.getRowCount();
    while (incidentGR.next()) {
      var incidentObj = {};
      incidentObj.number = incidentGR.getDisplayValue("number");
      incidentObj.caller = incidentGR.getDisplayValue("caller_id");
      incidentObj.category = incidentGR.getDisplayValue("category");
      incidentObj.shortDesc = incidentGR.getDisplayValue("short_description");
      incidentObj.dateCreated = incidentGR.getDisplayValue("sys_created_on");
      incidentObj.state = incidentGR.getDisplayValue("state");
      incArr.push(incidentObj);
    }
    return incArr;
  },
  type: "Incident_Utils ",
};

HTML Template:

<div class="card-demo">
  <div class="container">
    <div class="row">
      <div class="col-xl-12">
        <div class="col-md-3" ng-repeat="obj in c.data.incidentData">
          <div incident-cards item="obj"></div>
        </div>
      </div>
    </div>
  </div>
</div>

Server Script:

(function () {
  /* populate the 'data' object */
  /* e.g., data.table = $sp.getValue('table'); */
  var incidentUtils = new Incident_Utils();
  data.prevSearchTerm = "";
  data.currentPage = 1;
  data.maxSize = 4;
  data.incidentData = incidentUtils.getAllIncident(
    data.prevSearchTerm,
    data.currentPage,
    data.maxSize
  );
})();

Angular Provider (named "incidentCards"):

function() {
	
var templateString =  '<div class="col-xl-12 card-border">'+
	'            <div class="general-info">'+
	'              <div class="drilldown-block">'+
	'                <i'+
	'                  class="fa-solid fa-ellipsis"'+
	'                  data-toggle="modal"'+
	'                  data-target="#myModal"'+
	'                  ng-click="selectItem(c.item)"'+
	'                ></i>'+
	'              </div>'+
	'              <div class="incident-number">'+
	'                <div class="incident-number-question question">'+
	'                  Incident Number'+
	'                </div>'+
	'                <div class="incident-number-response response">{{c.item.number}}</div>'+
	'              </div>'+
	'              <div class="incident-name">'+
	'                <div class="incident-name question">Incident Name</div>'+
	'                <div class="incident-name response">{{c.item.shortDesc}}</div>'+
	'              </div>'+
	'            </div>'+
	'            <!-- Modal -->'+
	'            <div class="modal fade" id="myModal" role="dialog">'+
	'              <div class="modal-dialog modal-dialog-centered">'+
	'                <!-- Modal content-->'+
	'                <div class="modal-content">'+
	'                  <div class="modal-header">'+
	'                    <button type="button" class="close" data-dismiss="modal">'+
	'                      '+
	'                    </button>'+
	'                    <div class="col-xl-12 card-border-partner-modal">           '+
	'                      <div class="general-info">            '+
	'                        <div class="incident-number">'+
	'                          <div class="incident-number-question question">'+
	'                            Incident Name'+
	'                          </div>'+
	'                          <div class="incident-number-response response">{{c.item.number}}</div>'+
	'                        </div>'+
	'                        <div class="incident-name">'+
	'                          <div class="incident-name question">Incident Name</div>'+
	'                          <div class="incident-name response">{{c.item.shortDesc}}</div>'+
	'                        </div>'+
	'                      </div>'+
	'                    </div>'+
	'                  </div>'+
	'                </div>'+
	'              </div>'+
	'            </div>'+
	'          </div>';

	return {
		restrict: 'A',
		replace: true,
		template: templateString,
		scope: {
			item: "=",
		},
		bindToController: true,
		controllerAs: 'c',
		link: function(scope, element, attrs, ctrl) {

			if(ctrl.config) {
				angular.extend(ctrl, ctrl.config);
			}

			console.log(scope);
			console.log(attrs);	
			scope.selectItem = selectItem;
			function selectItem(event) {
				console.log(event);
				scope.c.item.number = event.number;
				scope.c.item.shortDesc = event.shortDesc;
			}
		},
		controller: function($timeout, $scope) {
			var c = this;
			// $scope.selectItem = selectItem;
			// $scope.incidentNumber = "Test Number";	
			// $scope.incidentDesc = "Test ShortDesc";	
			// function selectItem(event) {
			// 	console.log(event);
			// 	$scope.incidentNumber = event.number;
			// 	$scope.incidentDesc = event.shortDesc;
			// }

	
			$timeout(function() {
				$('#myModal').html(function(i, h) {
					return h.replace(/&nbsp;/g,'');
				})
			}, 1000);
		}
	}
}
1 ACCEPTED SOLUTION

Hoa Do
Kilo Guru

Hi everyone, 

I want to say that I have solved this issue. In this post, I would like to analyze some ideas that direct me to the solution.

Analyze: My first approach is using Bootstrap Modal in the AngularJS Directive because I think it is simple and convenient to implement. However, this method has a severe problem with data binding to the modal. As you know, Bootstrap in the ServiceNow Platform uses many methods of Jquery, which is sometimes hard to handle in some situations. Therefore, my alternative for this case is using BootstrapUI directives. This approach is very simple. You don't need to install any dependencies because it is already available in the ServiceNow Platform. Here are some of my images and codes (Script Include (named "Incident_Utils") and Script Include still remain):

HTML Template

<div class="card-demo">
  <div class="container">
    <div class="row">
      <div class="col-xl-12">
        <div class="col-md-3" ng-repeat="obj in c.data.incidentData">
          <incident-cards item="obj"></incident-cards>
        </div>
      </div>
    </div>
  </div>
</div>

Angular Provider (named "incidentCards"):

function() {
	return {
		restrict: 'EA',
		template: '<div class="col-xl-12 card-border">'+
		'            <div class="general-info">'+
		'              <div class="drilldown-block">'+
		' <i class="fa-solid fa-ellipsis" ng-click="selectItem(vm.item)" ></i>'        +
		'              </div>'+
		'              <div class="incident-number">'+
		'                <div class="incident-number-question question">'+
		'                  Incident Number'+
		'                </div>'+
		'                <div class="incident-number-response response">{{vm.item.number}}</div>'+
		'              </div>'+
		'              <div class="incident-name">'+
		'                <div class="incident-name question">Incident Name</div>'+
		'                <div class="incident-name response">{{vm.item.shortDesc}}</div>'+
		'              </div>'+
		'          </div>',
		scope: {
			item: "="
		},
		controllerAs: 'vm',
		bindToController: true,
		link: function(scope, element, attrs, ctrl) {
			if(ctrl.config) {
				angular.extend(ctrl, ctrl.config);
			}
			console.log(arguments);
		},
		controller: function($uibModal, $scope, $timeout) {
			var vm = this;

    	                $scope.closeModal = closeModal;
			$scope.selectItem = selectItem;
			$scope.dataFake = {};

			function closeModal() {
				vm.modalInstance.close();
			}

			function selectItem(event) {
				vm.modalInstance = $uibModal.open({
					template: ' <!-- Modal -->'+
							'                <div class="modal-content">'+
							'                  <div class="modal-header">'+
							'                    <button type="button" ng-click="closeModal()" >'+
							'                     &times;'+
							'                    </button>'+
										'                    <div class="col-xl-12 card-border-partner-modal">           '+
										'                      	<div class="general-info">            '+
												'                        <div class="incident-number">'+
													'                          <div class="incident-number-question question">'+
													'                            Incident Number'+
													'                          </div>'+
											'                          		 <div class="incident-number-response response">{{dataFake.number}}</div>'+
												'                        </div>'+
												'                        <div class="incident-name">'+
												'                          <div class="incident-name question">Incident Name</div>'+
												'                          <div class="incident-name response"> {{dataFake.shortDesc}} </div>'+
												'                        </div>'+
										'                      	</div>'+
										'                    </div>'+
							'                  </div>'+
							'                </div>',
							scope: $scope
				});
				console.log("1: " + JSON.stringify(event));

				$scope.dataFake = event;
				console.log("2: " + JSON.stringify($scope.dataFake));
			}

			$scope.$watch('dataFake', function () {
				console.log("3: " + JSON.stringify($scope.dataFake));
			});

			$timeout(function() {
				$('#myModal').html(function(i, h) {
					return h.replace(/&nbsp;/g,'');
				})
			}, 2000);
		}
	}
}

That is my solution. If you feel this post is good, please give me a helpful icon below. Thank you so much!

 

 

View solution in original post

2 REPLIES 2

Mahesh23
Mega Sage

Hello,

Please refer below video might help you

https://youtu.be/h72ZO88p7t8

 

 

Hoa Do
Kilo Guru

Hi everyone, 

I want to say that I have solved this issue. In this post, I would like to analyze some ideas that direct me to the solution.

Analyze: My first approach is using Bootstrap Modal in the AngularJS Directive because I think it is simple and convenient to implement. However, this method has a severe problem with data binding to the modal. As you know, Bootstrap in the ServiceNow Platform uses many methods of Jquery, which is sometimes hard to handle in some situations. Therefore, my alternative for this case is using BootstrapUI directives. This approach is very simple. You don't need to install any dependencies because it is already available in the ServiceNow Platform. Here are some of my images and codes (Script Include (named "Incident_Utils") and Script Include still remain):

HTML Template

<div class="card-demo">
  <div class="container">
    <div class="row">
      <div class="col-xl-12">
        <div class="col-md-3" ng-repeat="obj in c.data.incidentData">
          <incident-cards item="obj"></incident-cards>
        </div>
      </div>
    </div>
  </div>
</div>

Angular Provider (named "incidentCards"):

function() {
	return {
		restrict: 'EA',
		template: '<div class="col-xl-12 card-border">'+
		'            <div class="general-info">'+
		'              <div class="drilldown-block">'+
		' <i class="fa-solid fa-ellipsis" ng-click="selectItem(vm.item)" ></i>'        +
		'              </div>'+
		'              <div class="incident-number">'+
		'                <div class="incident-number-question question">'+
		'                  Incident Number'+
		'                </div>'+
		'                <div class="incident-number-response response">{{vm.item.number}}</div>'+
		'              </div>'+
		'              <div class="incident-name">'+
		'                <div class="incident-name question">Incident Name</div>'+
		'                <div class="incident-name response">{{vm.item.shortDesc}}</div>'+
		'              </div>'+
		'          </div>',
		scope: {
			item: "="
		},
		controllerAs: 'vm',
		bindToController: true,
		link: function(scope, element, attrs, ctrl) {
			if(ctrl.config) {
				angular.extend(ctrl, ctrl.config);
			}
			console.log(arguments);
		},
		controller: function($uibModal, $scope, $timeout) {
			var vm = this;

    	                $scope.closeModal = closeModal;
			$scope.selectItem = selectItem;
			$scope.dataFake = {};

			function closeModal() {
				vm.modalInstance.close();
			}

			function selectItem(event) {
				vm.modalInstance = $uibModal.open({
					template: ' <!-- Modal -->'+
							'                <div class="modal-content">'+
							'                  <div class="modal-header">'+
							'                    <button type="button" ng-click="closeModal()" >'+
							'                     &times;'+
							'                    </button>'+
										'                    <div class="col-xl-12 card-border-partner-modal">           '+
										'                      	<div class="general-info">            '+
												'                        <div class="incident-number">'+
													'                          <div class="incident-number-question question">'+
													'                            Incident Number'+
													'                          </div>'+
											'                          		 <div class="incident-number-response response">{{dataFake.number}}</div>'+
												'                        </div>'+
												'                        <div class="incident-name">'+
												'                          <div class="incident-name question">Incident Name</div>'+
												'                          <div class="incident-name response"> {{dataFake.shortDesc}} </div>'+
												'                        </div>'+
										'                      	</div>'+
										'                    </div>'+
							'                  </div>'+
							'                </div>',
							scope: $scope
				});
				console.log("1: " + JSON.stringify(event));

				$scope.dataFake = event;
				console.log("2: " + JSON.stringify($scope.dataFake));
			}

			$scope.$watch('dataFake', function () {
				console.log("3: " + JSON.stringify($scope.dataFake));
			});

			$timeout(function() {
				$('#myModal').html(function(i, h) {
					return h.replace(/&nbsp;/g,'');
				})
			}, 2000);
		}
	}
}

That is my solution. If you feel this post is good, please give me a helpful icon below. Thank you so much!