0

I have an Angular function within a PHP partial page that appears to not be working properly. The function is attached to all images that are loaded on to the page from a MySQL database, and is called with ng-click="vm.openModal('custom-modal-1')".

<div id="screenings">
    <?php
    ...
    //connect to MySQL database
    ...
        while ($row = mysqli_fetch_array($result)){
            echo "<div class='img_div'>";?>

                //here is the ng-click that calls the Angular function

                <img class="modal_img img_screenings" ng-click="vm.openModal('custom-modal-1')" src='images/<?php echo $row['image']."' >";
            ...
            echo "</div>";
        }
    ?>

</div>

//here is the modal with the id that gets passed to the Angular function

<modal id="custom-modal-1">
    <div class="modal">
        <div class="modal-body">
                <img id="popup_img" src="#">
        </div>
    </div>
    <div class="modal-background"></div>
</modal>

Within the file app.js, here is the function that I'm trying to call:

app.controller('screeningsController', ['$scope', '$log', "ModalService", function($scope, $log, ModalService){

    var vm = this;

    //outputs "Hello World!" to browser console as a test
    vm.message = "Hello World!";
    $log.log(vm.message);

    vm.openModal = openModal;
    vm.closeModal = closeModal;

    function openModal(id){
        ModalService.Open(id);
    }

    function closeModal(id){
        ModalService.Close(id);
    }

}]);

When the partial page is loaded in, the test message "Hello World!" that is found within the Angular function fires, and the message appears in the browser console. However, the ng-click doesn't do anything else when any img with class modal_img is clicked on the page.

All Angular modal window materials for this code was taken from: http://jasonwatmore.com/post/2016/07/13/angularjs-custom-modal-example-tutorial

EDIT Controller as is declared at the top of the app.js file, like so:

var app = angular.module('app', ['ngRoute', 'ui.router']);

app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {

$locationProvider.hashPrefix('');

$urlRouterProvider.otherwise("/");

 $stateProvider

 .state('home', {
    url: '/',
    templateUrl: 'pages/main.html',
    controller: 'mainController',
    controllerAs: 'vm'
 })

 .state('screenings', {
    url: '/screenings',
    templateUrl: 'pages/screenings.php',
    controller: 'screeningsController',
    controllerAs: 'vm'
 })

 //etc
rpivovar
  • 3,150
  • 13
  • 41
  • 79

1 Answers1

1

For ng-click="vm.openModal('custom-modal-1')" to work you need to define what is vm.

In AngularJS a template expression is evaluated in the angular scope.

So you will need to tell the template that you intend to use screeningsController.

It is like defining a variable/object instance in a block of code up so that the code block can use that.

Only then the template can use the controller functions or scope functions.

So there are two ways how you can expose controller properties/functions.

1) By populating functions and variables on $scope 2) By populating the controller function using this like you used var vm = this;

In your case your vm.openModal will be available to every element under id="screenings" if you declare that HTML element as below.

<div ng-controller="screeningsController" id="screenings">

However in order to user controller function populated on this one must use controller as syntax. So the above line becomes this:

<div ng-controller="screeningsController as vm" id="screenings">

In the above line you are saying that vm is screeningsController.

It is best to use something more meaningful than just vm in case you end up using more than 1 controller say nested controllers.

So one might just call vm as what it is - in this case screeningsController

<div ng-controller="screeningsController as screeningsController" id="screenings"> and the ng-click becomes ng-click="screeningsController.openModal('custom-modal-1')"

If screeningsController as screeningsController feels weird I would change that to ScreeningsController as screeningsController where by you are essentially saying screeningsController is ScreeningsController. Hence you might want to define app.controller('screeningsController' as rather app.controller('ScreeningsController'

Its like giving a name to the Controller class/constructor so why not start with Capital case.

You can checkout official Angular ngController documentation and the example

Most of what I have recommended is for following best conventions. If everything else is correct your problem should just get resolved merely by
<div ng-controller="screeningsController as vm" id="screenings">

You may place ngController at other appropriate places but it must be some ancestor to your ng-click which needs access to that controller.

bhantol
  • 9,368
  • 7
  • 44
  • 81
  • Thank you for the incredibly thorough answer..someone was telling me about the difference between `this` and `$scope`, but this was a bit more thorough, so I appreciate that. Unfortunately `
    ` did not seem to fix it, though the test message `"Hello World!"` seems to fire twice now.
    – rpivovar May 15 '17 at 02:38
  • The tutorial doesn't appear to be using `ng-controller as` in their page either. – rpivovar May 15 '17 at 02:40
  • Actually, he posts it when he declares his states - let me update my question with this code. – rpivovar May 15 '17 at 02:42
  • 1
    I suggest that you copy the HTML from browser after PHP has rendered from the server . Best is create a plnkr out of that HTML from browser - with small tweaking problem can be reproduced and fixed quite fast. – bhantol May 15 '17 at 02:42
  • Partial PHP page is loaded within `` – rpivovar May 15 '17 at 02:49
  • I see module error in browser console. It is saying that `app` is not a module this is due to many files getting 404 and not being fetched. e.g. ` ` – bhantol May 15 '17 at 02:59
  • 1
    These file need to be added to the plnkr. – bhantol May 15 '17 at 03:00
  • Sorry, I'm terrible at using plunker. One moment. – rpivovar May 15 '17 at 03:00
  • Okay, my apologies. All four of those should be in there now. – rpivovar May 15 '17 at 03:04
  • Would it help if I prepared a plunker with a working example from the tutorial? – rpivovar May 15 '17 at 03:27
  • 1
    Tried to fix your plnkr https://plnkr.co/edit/mJvhii7Mb9vUt281gY6N?p=preview but it seems there are fundamental differenrces in the example. You have everything moved to index,html. main.html was missing so I moved some content to main.html. Probably creating plnkr f the example might be best. – bhantol May 15 '17 at 03:37
  • thank you for all your help. I will do that and get back to you. – rpivovar May 15 '17 at 03:40
  • I feel like maybe my less.js is not working properly – rpivovar May 15 '17 at 04:29
  • 1
    Ah it was the less.js!!!!!! I finally got it working after a week of not knowing what was going on. I'm accepting your answer anyway. God bless America. – rpivovar May 15 '17 at 05:05