Reputation: 88
I'm doing a simple angular example but can't quite figure out why it is not working. I seem to have found where it fails, but not why.
This does work (direcly calling the Test2 function):
Init();
Test1();
Test2(); //**DIRECTLY CALL THIS METHOD**
function Init() {
window.app = angular.module('MyApp', []);
}
function Test1() {
app.controller('MySelectCtrl', function ($scope) {
alert(1);
});
}
function Test2() {
app.controller('MySelectCtrl2', function ($scope) {
alert(2);
});
}
<div data-ng-app="MyApp" >
<p>
<select data-ng-controller="MySelectCtrl" name="repeatSelect" id="repeatSelect" data-ng-model="data.model">
<option data-ng-repeat="option in MyNames" value="{{$index}}">{{MyNames}}</option>
</select>
</p>
<p>
<select disabled="" data-ng-controller="MySelectCtrl2" name="repeatSelect2" id="repeatSelect2" data-ng-model="data.model2" >
<option data-ng-repeat="option in MyNames2" value="{{$index}}">{{MyNames2}}</option></option>
</select>
</p>
</div>
While this doesn't work (calling the Test2 function in the onclick):
Init();
Test1();
//Test2(); **CALLING THIS THROUGH ONCLICK IN THE FIRST SELECT BELOW**
function Init() {
window.app = angular.module('MyApp', []);
}
function Test1() {
app.controller('MySelectCtrl', function ($scope) {
alert(1);
});
}
function Test2() {
app.controller('MySelectCtrl2', function ($scope) {
alert(2);
});
}
<div data-ng-app="MyApp" >
<p>
<select data-ng-controller="MySelectCtrl" name="repeatSelect" id="repeatSelect" data-ng-model="data.model" onclick="Test2();">
<option data-ng-repeat="option in MyNames" value="{{$index}}">{{MyNames}}</option>
</select>
</p>
<p>
<select disabled="" data-ng-controller="MySelectCtrl2" name="repeatSelect2" id="repeatSelect2" data-ng-model="data.model2" >
<option data-ng-repeat="option in MyNames2" value="{{$index}}">{{MyNames2}}</option></option>
</select>
</p>
</div>
How can I only run Test2() in the onclick (ie get to execute alert(2) when the first select is clicked)?
Note: The above is just a minified test. In reality I want the second select to be populated ($http ajax call) with items depending on what was selected in the first select. Should I be using a different approach to bind that data?
Upvotes: 1
Views: 314
Reputation: 26
Using the link posted by Edmar Miyake. I created a Plunkr with your code that will give you the behavior you expect:
https://plnkr.co/edit/aRr6JaTipXdTVACYOGuf?p=preview
NOTE: Clicking on the first select element will not load the second select element until you either click away from the menu (i.e. closing it, or selecting a value). If you want the second element loaded after simply clicking the first, you need to use 'data-ng-mousedown' instead of 'data-ng-click'.
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<script type="text/javascript">
Init();
function Init() {
window.app = angular.module('plunker', []);
/*
Overriding main components using pattern from
https://www.bennadel.com/blog/2553-loading-angularjs-components-after-your-application-has-been-bootstrapped.htm
*/
app.config(function ($controllerProvider, $provide, $compileProvider) {
console.log('config method ran');
app._controller = app.controller;
app._service = app.service;
app.factory = app.factory;
app._value = app.value;
app._directive = app.directive;
// provider-based controller
app.controller = function (name, constructor) {
$controllerProvider.register(name, constructor);
return(this);
};
// provider-based service
app.service = function (name, constructor) {
$provide.service(name, constructor);
return(this);
};
// provider-based factory
app.factory = function (name, factory) {
$provide.factory(name, factory);
return(this);
};
// provider-based value
app.value = function (name, value) {
$provide.value(name, value);
return(this);
};
// provider-based directive
app.directive = function (name, factory) {
$compileProvider.directive(name, factory);
return(this);
};
});
app.controller('appCtrl', function ($scope) {
/* showSecondSelectCtrl will control when Angular loads the second select element into the DOM */
$scope.showSecondSelectCtrl = false;
Test1();
$scope.Test2 = function () {
console.log('adding MySelectCtrl2');
app.controller('MySelectCtrl2', function ($scope) {
alert(2);
$scope.MyNames2 = ['nai', 'aru', 'machi'];
});
$scope.showSecondSelectCtrl = true;
}
});
}
/* Exposing this function on the global object is not "The Angular Way" of doing things.
Test1 should live inside of an Angular controller like Test2 does. */
function Test1() {
console.log('adding MySelectCtrl');
app.controller('MySelectCtrl', function ($scope) {
// alert(1);
$scope.MyNames = ['biff', 'marty', 'doc'];
});
}
</script>
</head>
<!-- auto-bootstrap Angular app with the name of 'plunker' -->
<body data-ng-app="plunker">
<!-- Specify a controller to allow dynamic rendering of second select element -->
<div data-ng-controller="appCtrl">
<p>
<!-- Using Angular's ng-click directive since Test2 should live inside of appCtrl -->
<select data-ng-controller="MySelectCtrl" name="repeatSelect" id="repeatSelect" data-ng-model="data.model" data-ng-click="Test2();">
<option value="">My Names</option>
<option data-ng-repeat="option in MyNames" value="{{$index}}">{{option}}</option>
</select>
</p>
<!-- We cannot render the second select element until the 'MySelectCtrl2' controller exists.
Since we are dynamically loading it, we need to hide it from the DOM until it is loaded
using ng-if -->
<p data-ng-if="showSecondSelectCtrl">
<select data-ng-controller="MySelectCtrl2" name="repeatSelect2" id="repeatSelect2" data-ng-model="data.model2" >
<option value="">My Names2</option>
<option data-ng-repeat="option in MyNames2" value="{{$index}}">{{option}}</option>
</select>
</p>
</div>
</body>
</html>
Upvotes: 1
Reputation: 88
The solution seems to be one controller and two modules: jsfiddle.net/TheSharpieOne/Xku9z/1
Populate Dropdown 2 based on Dropdown 1 selection
Upvotes: 0
Reputation: 12390
I don't think it will work. You are trying to add a new controller after your application has been already bootstrapped (lazy binding).
Take a look at this article. It will show you how you can do it: https://www.bennadel.com/blog/2553-loading-angularjs-components-after-your-application-has-been-bootstrapped.htm
Upvotes: 0