Sathish
Sathish

Reputation: 319

angularJs component and controller

I have created angular component and the code looks below:

(function () {
    'use strict';
    angular
        .module('App', ['ngMaterial']).component('autoComplete', {
            template: '<div layout="column" ng-cloak>\
                        <md-content class="md-padding">\
                            <form ng-submit="$event.preventDefault()">\
                                <md-autocomplete ng-disabled="$ctrl.isDisabled"\
                                    md-no-cache="$ctrl.noCache"\
                                    md-selected-item="$ctrl.selectedItem"\
                                    md-search-text-change="$ctrl.searchTextChange($ctrl.searchText)"\
                                    md-search-text="$ctrl.searchText"\
                                    md-selected-item-change="$ctrl.selectedItemChange(item)"\
                                    md-items="item in $ctrl.querySearch($ctrl.searchText)"\
                                    md-item-text="item.display"\
                                    md-min-length="0"\
                                    placeholder="Search State">\
                                <md-item-template>\
                                <span md-highlight-text="$ctrl.searchText" md-highlight-flags="^i">{{item.display}}</span>\
                                </md-item-template>\
                                <md-not-found>\
                                No states matching "{{$ctrl.searchText}}" were found.\
                                <a ng-click="$ctrl.newState($ctrl.searchText)">Create a new one!</a>\
                                </md-not-found>\
                                </md-autocomplete>\
                                <br />\
                            </form>\
                        </md-content>\
                    </div>',
            controller: function DemoCtrl($timeout, $q, $log, $http) {
                $log.info('Called');
                var self = this;

                self.simulateQuery = false;
                self.isDisabled = false;

                // list of `state` value/display objects
                self.states = loadAll($http);
                self.querySearch = querySearch;
                self.selectedItemChange = selectedItemChange;
                self.searchTextChange = searchTextChange;

                self.newState = newState;

                function newState(state) {
                    alert("Sorry! You'll need to create a Constitution for " + state + " first!");
                }

                // ******************************
                // Internal methods
                // ******************************

                /**
                 * Search for states... use $timeout to simulate
                 * remote dataservice call.
                 */
                function querySearch(query) {
                    //var results = query ? self.states.filter(createFilterFor(query)) : self.states,
                    //    deferred;
                    //if (self.simulateQuery) {
                    //    deferred = $q.defer();
                    //    $timeout(function () { deferred.resolve(results); }, Math.random() * 1000, false);
                    //    return deferred.promise;
                    //} else {
                    //    return results;
                    //}
                    var allStates;
                    return $http.get("/Home/GetStates", { params: { q: query } })
                    .then(function (response) {
                        allStates = response;
                        return allStates.data.split(/, +/g).map(function (state) {
                            return {
                                value: state.toLowerCase(),
                                display: state
                            };
                        });
                    })
                    //$http({
                    //    method: 'GET',
                    //    url: '/Home/GetStates'
                    //}).then(function successCallback(response) {
                    //    allStates = response;

                    //}, function errorCallback(response) {
                    //    alert(response);
                    //    return false;
                    //});
                }

                function searchTextChange(text) {
                    $log.info('Text changed to ' + text);
                }

                function selectedItemChange(item) {
                    $log.info('Item changed to ' + JSON.stringify(item));
                }

                /**
                 * Build `states` list of key/value pairs
                 */
                function loadAll($http) {
                    //var allStates;
                    //$http({
                    //    method: 'GET',
                    //    url: '/Home/GetStates'
                    //}).then(function successCallback(response) {
                    //    allStates = response;
                    //    return allStates.split(/, +/g).map(function (state) {
                    //        return {
                    //            value: state.toLowerCase(),
                    //            display: state
                    //        };
                    //    });
                    //}, function errorCallback(response) {
                    //    alert(response);
                    //    return false;
                    //});            
                }

                /**
                 * Create filter function for a query string
                 */
                function createFilterFor(query) {
                    var lowercaseQuery = angular.lowercase(query);

                    return function filterFn(state) {
                        return (state.value.indexOf(lowercaseQuery) === 0);
                    };

                }
            }
        })
})();

and i have created a one more controller in new javascript file and it looks below.

(function () {
    var app = angular.module("App", []);
    var TestController = function ($scope) {
        $scope.Display = "Test Display";
    };
    app.controller("TestController", ["$scope", TestController]);
}());

Here is my HTML

<html ng-app="App" ng-cloak>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/angular.min.js"></script>
    <!-- Angular Material requires Angular.js Libraries -->
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>

    <!-- Angular Material Library -->
    <script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.js"></script>

    <script type="text/javascript">
        /**
         * You must include the dependency on 'ngMaterial'
         */
        angular.module('App', ['ngMaterial']);
        
    </script>
    <script src="~/Scripts/TestAngular.js"></script>
    <script src="~/Scripts/Component/auto-complete.component.js"></script>
    <!-- Your application bootstrap  -->

    

    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">
</head>
<body>
    <div ng-controller="TestController">
        <input type="text" ng-model="Display" />
        {{Display}}
    </div>
    <auto-complete></auto-complete>
    
</body>
</html>

when tried to run this HTML, i am getting Testcontroller registration error. But if i remove auto-complete.component.js then TestController is working fine. Please help me to solve this issue.

Upvotes: 0

Views: 695

Answers (2)

Ulysse BN
Ulysse BN

Reputation: 11423

You are messing with your module declaration, either declare it once, or do it right.

Doing it right

Once you’ve declared your module, you can access it with

angular.module('App')

So in your html file nothing changes, but in both other files, replace angular.module('App',[..]) byangular.module('App').

This is the best practice to achieve it, keeping each component separated in isolated (function(){ .. })() blocks

Declaring it once

For your issue, I solved by changing the first called script (inline in html) to:

var app = angular.module('App', ['ngMaterial']);

Then I used this variable instead of redefining a new module each time :

(function(app){
   // controller or component here
}(app));

This did the trick, however this migth be some more complicated module overwritting. Moreover, you should avoid global variable as such

My TestController:

(function (app) {
    var TestController = function ($scope) {
        $scope.Display = "Test Display";
    };
    app.controller("TestController", ["$scope", TestController]);
}(app));

My autocomplete component:

(function (app) {
    'use strict';
    app.component('autoComplete', {
      // ...
    })
})(app);

Upvotes: 1

Sravan
Sravan

Reputation: 18657

Error: Module should be created only once in all the application.

You have created a module for a component and also for the controller which is wrong. Create for one and use in the second.

In your controller,

var app = angular.module("App", []);

Should be,

var app = angular.module("App");

Controller:

(function () {
    var app = angular.module("App");
    var TestController = function ($scope) {
        $scope.Display = "Test Display";
    };
    app.controller("TestController", ["$scope", TestController]);
}());

Check the line,

var app = angular.module("App");

Upvotes: 2

Related Questions