I am unable to access Angular $scope in the HTML Template, although I can view it in the console log

I have been following some online tutorials and using the angularjs-template to start learning Angular. However, I am facing an issue where the page (html template) is not updating with the controller. It seems like there is a problem in how I've set up the controller because the values are not being displayed in the html template.

I tried implementing recommendations from best practice guides by wrapping my components in an 'Invoked Function Expression' and separating out the controller, service, and service manager. But it looks like I've messed this up somewhere and need assistance in identifying the mistake.

When checking the console, I can see that $scope.metric contains the desired information, indicating that the controller has successfully retrieved data from the API via the metricService. However, I'm unable to display these results on the html page e.g. metric.id.

Any help would be greatly appreciated as I've exhausted all my efforts trying to resolve this issue.

metric.html

<div class="panel panel-primary">
<div class="panel-body">
     <!-- Try First Way to Print Results -->
    Id: <span ng-bind="metric.id"></span></br>
    Name:<input type="text" ng-model="metric.metadata.name" /></br>

    <!-- Try Second Way to Print Results -->
    <p data-ng-repeat="thing in ::MEC.metric track by $index">
        {{$index + 1}}. <span>{{thing.metadata.name}}</span>
            <span class="glyphicon glyphicon-info-sign"></span>
        </a>
    </p>

<!-- Try Third Way to Print Results -->
    Id: <span ng-bind="Metric.metricId"></span></br>
    Id: <span ng-bind="Metric.id"></span></br>
    Id: <span ng-bind="metricService.id"></span></br>

<!-- Try Fourth Way to Print Results -->
      Id: <strong>{{::MEC.metric.id}}</strong></br>
      Name: <strong>{{::MEC.metric.metadata.name}}</strong></br>
      Height: <strong>{{::MEC.metric.type}}</strong>
</div>

metricController.js

(function () {
    'use strict';

    angular.module('app.metric', ['app.metricService', 'app.metricManager'])    
        .controller('MetricController', MetricController) 

        MetricController.$inject = ['$scope', 'metricManager', '$log'];

        function MetricController($scope, metricManager, $log) {

            metricManager.getMetric(0).then(function(metric) {
                $scope.metric = metric
                $log.info('$scope.metric printed to console below:');
                $log.info($scope.metric);
            })
        }
})();

metricService.js

(function () {
    'use strict';

    angular.module('app.metricService', [])    

    .factory('Metric', ['$http', '$log', function($http, $log) {  
        function Metric(metricData) {
            if (metricData) {
                this.setData(metricData);
            }
            // Some other initializations related to book
        };

        Metric.prototype = {
            setData: function(metricData) {
                angular.extend(this, metricData);
            },

            delete: function() {
                $http.delete('https://n4nite-api-n4nite.c9users.io/v1/imm/metrics/' + metricId);
            },

            update: function() {
                $http.put('https://n4nite-api-n4nite.c9users.io/v1/imm/metrics/' + metricId, this);
            },

            hasMetadata: function() {
                if (!this.metric.metadata || this.metric.metadata.length === 0) {
                    return false;
                }
                return this.metric.metadata.some(function(metadata) {
                    return true
                });
            }
        };
        return Metric;
    }]);

})();

metricManager.js

(function () {
    'use strict';

    angular.module('app.metricManager', [])   

    .factory('metricManager', ['$http', '$q', 'Metric', function($http, $q, Metric) {  
    var metricManager = {
        _pool: {},
        _retrieveInstance: function(metricId, metricData) {
            var instance = this._pool[metricId];

            if (instance) {
                instance.setData(metricData);
            } else {
                instance = new Metric(metricData);
                this._pool[metricId] = instance;
            }

            return instance;
        },
        _search: function(metricId) {
            return this._pool[metricId];
        },
        _load: function(metricId, deferred) {
            var scope = this;

            $http.get('https://n4nite-api-n4nite.c9users.io/v1/imm/metrics/' + metricId).then(successCallback, errorCallback)

                function successCallback(metricData){
                    //success code
                    var metric = scope._retrieveInstance(metricData.id, metricData);
                    deferred.resolve(metric);
                };

                function errorCallback(error){
                    //error code
                    deferred.reject();
                }
        },

        /* Public Methods */
        /* Use this function in order to get a metric instance by it's id */
        getMetric: function(metricId) {
            var deferred = $q.defer();
            var metric = this._search(metricId);
            if (metric) {
                deferred.resolve(metric);
            } else {
                this._load(metricId, deferred);
            }
            return deferred.promise;
        },

        /* Use this function in order to get instances of all the metrics */
        loadAllMetrics: function() {
            var deferred = $q.defer();
            var scope = this;
            $http.get('ourserver/books')
                .success(function(metricsArray) {
                    var metrics = [];
                    metricsArray.forEach(function(metricData) {
                        var metric = scope._retrieveInstance(metricData.id, metricData);
                        metrics.push(metric);
                    });

                    deferred.resolve(metrics);
                })
                .error(function() {
                    deferred.reject();
                });
            return deferred.promise;
        },

        /*  This function is useful when we got somehow the metric data and we wish to store it or update the pool and get a metric instance in return */
        setMetric: function(metricData) {
            var scope = this;
            var metric = this._search(metricData.id);
            if (metric) {
                metric.setData(metricData);
            } else {
                metric = scope._retrieveInstance(metricData);
            }
            return metric;
        },

    };
    return metricManager;
}]);
})();

Snippet from App.routes

 .state('root.metric', {
                    url: 'metric',
                    data: {
                        title: 'Metric',
                        breadcrumb: 'Metric'
                    },
                    views: {
                        'content@': {
                            templateUrl: 'core/features/metric/metric.html',
                            controller: 'MetricController',
                            controllerAs: 'MEC'
                        }
                    }
                })

Console https://github.com/pamigomp/angularjs-template

Answer №1

When setting up a controller alias with `$scope`, it is important to understand the difference between the two concepts. In this example, the controller alias is created as MEC using the `controllerAs` syntax. If you utilize controller alias, your code should look like this:

function MetricController($scope, metricManager, $log) {
    var MEC = this;
    metricManager.getMetric(0).then(function(metric) {
        MEC.metric = metric
        $log.info('$scope.metric printed to console below:');
        $log.info($scope.metric);
    })
}

If you prefer not to use a controller alias and instead share data between the view and controller via `$scope`, you can use a syntax like {{::metric.metadata.name}} in your view while keeping the controller function unchanged.

Furthermore, when choosing an alias name like MEC or abc, it is best practice to adhere to the convention of using `var vm = this` and `controllerAs: 'vm'`. If you define the controllerAs as 'xyz', then in your view, you should access the model using `xyz`.

Answer №2

There seems to be an issue with the HTML in your view. Make sure you are using Angular expressions correctly when binding data. If you want to use the alias name ::MEC, you need to specify your controller with the as keyword, like this: ng-controller="xyz as MEC". You can also refer to a working example on Plunker.

<div class="panel panel-primary">
    <div class="panel-body">
        <!-- Try First Way to Print Results -->
        Id: <span ng-bind="metric.id"></span>
        <br> Name:
        <input type="text" ng-model="metric.metadata.name" />
        <br><br><br><br>

        <!-- Try Second Way to Print Results -->
        <p data-ng-repeat="thing in [metric] track by $index">
            {{$index + 1}}. <span>{{thing.metadata.name}}</span>
            <span class="glyphicon glyphicon-info-sign"></span>
        </p><br><br><br>

        <!-- Try Third Way to Print Results -->
        Id: <span ng-bind="metric.metricId"></span>
        <br> Id: <span ng-bind="metric.id"></span>
        <br><br><br>

        <!-- Try Fourth Way to Print Results -->
        Id: <strong>{{::metric.id}}</strong>
        <br> Name: <strong>{{::metric.metadata.name}}</strong>
        <br> Height: <strong>{{::metric.type}}</strong>
    </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble displaying HTML UL content conditionally in Reactjs?

My goal is to display a list of items, limited to a maximum of 5 items, with a "more" button that appears conditionally based on the number of items in the list. However, I am encountering an issue where passing in 5 li items causes them to be rendered as ...

What exactly is the function of registerServiceWorker in React JS?

Just starting out with React and I have a question about the function of registerServiceWorker() in this code snippet: import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import registerServi ...

The Redux state fails to start with the default initial state

I'm a newcomer to react-redux. In my reducer, I have the following structure: const initialState = { Low: [ { id: 0, technologyId: 0, technology: '', type: '', ...

Having trouble with the functionality of the cascading menu?

I am having trouble with a drop-down menu. The first level works fine, but I can't seem to get the second level of the menu to display. Appreciate any help you can offer. Thank you. javascript <script type="text/javascript"> $(document).ready( ...

Triggering the 'change' event on a hidden value in jQuery can cause issues with knockout dependent observables

Let me share the story of how we stumbled upon this issue... Basically, we were invoking trigger('change') on all our form inputs to notify other knockout observables that their values had been reset. However, we suspect it could be a bug in Knoc ...

Ways to confirm the presence of strings within an array?

For instance: var array = ["apple", "banana", "cherry", "date", "elderberry", "fig"]; What is the best way to determine if "apple", "banana", and "cherry" are present in the array? I attempted using the indexOf() method but struggled to check for multip ...

Enhancing the Rendering of React's props.children

I have set up my code like this: // Parent.js class Parent extends React.Component { render() { return { this.props.children } } } // Child.js class Child extends React.Component { render() { let message; const greet = ...

I am encountering a problem while performing JavaScript validations

In jQuery or using the element's ID, I can validate a textbox. For example: var field = document.getElementById('tbxSearchField').value if (field == "") {alert("please enter text");} The HTML code is as follows: <input class="input" id ...

Challenges with Input Nesting

Why is the word "undefined" appearing on top of my text? function printName() { document.write('My name is John Doe.'); } function printAge() { printName(); document.write('I am 47 years old.'); } document.querySelector(&ap ...

What is the best approach to configure Nuxt.js to recognize both `/` and `/index.html` URLs?

Currently, I have set up my Nuxt.js in default mode with universal and history router configurations. After running nuxt generate, the generated website includes an index.html file in the dist folder. This means that when the website is published, it can ...

Tips on running methods consecutively within ngOnInit in Angular

I'm currently working on an ngoninit function that contains four methods. Two of these methods are responsible for retrieving data from the API, while the other two are intended to load this data when the page loads. ngOnInit(){ getname(); getsubjects ...

Tips on swapping out a part in ExtJS

Currently, my ExtJS window features a toolbar at the top and loads with a plain Panel at the bottom containing plain HTML. Everything is working smoothly in this setup. However, I now wish to replace this bottom panel (referred to as 'content') w ...

Revamp your arrays with input fields in Vue3

When presented with two arrays of options, users must select an option from each array. ==> first array: [ orange, green, yellow ] ==> second array: [ orange, green, yellow ] The challenge is to update the second array based on the user's sele ...

What sets apart "import { pick } from 'lodash';" from "import pick from 'lodash/pick';"?

Can you explain the difference between import { pick } from 'lodash'; and import pick from 'lodash/pick'; (Keep in mind that it's 'lodash/pick' in the second one, not just 'lodash'.) How do they each impact ...

List Elements Not Displaying Correctly due to CSS Styling Issues

After spending several hours trying to solve this problem, I've hit a roadblock. The challenge lies in dynamically adding items to a list using JavaScript and the Dojo library. I've experimented with both vanilla JS and Dojo code, ruling that pa ...

"Even when hidden, an HTML Div element still occupies space on the

I encountered an issue with my tabbedPage setup. Even though I have hidden content, it still occupies space on the page. Here is the code snippet that I am using: let tabHeader = document.getElementsByClassName("tabbedpage-header")[0]; let tabIndicator = d ...

Unable to use NodeJS await/async within an object

I'm currently developing a validation module using nodeJs and I'm facing difficulties understanding why the async/await feature is not functioning correctly in my current module. Within this module, I need to have multiple exports for validation ...

React Bootstrap always displays tooltips

I have integrated react-bootstrap into my project. I am currently attempting to keep a tooltip always displayed, but I am facing some challenges in achieving this. Below are the approaches I have tried so far: <Card style={{width: '10rem'}} ...

ajax - unable to fetch information from the same domain

UPDATE: The solution provided by Cavid Kərimov indeed works. By setting the form as shown below, it also resolves the issue. <form onsubmit="return false;"></form> I am attempting to fetch a simple text string from a PHP file using jQuery an ...

What is the best way to retrieve the reference value from a dropdown box and pass it to another component?

Currently, I am in the process of creating a chat application using socket.io. Within this application, there is a dashboard component that consists of two child components known as Room.js and Chat.js. The Room component serves the purpose of selecting th ...