AngularJS ng-click and nothing happens - angularjs

AngularJS
var theApp = angular.module('theApp', []);
theApp.controller('ContentController', ['$scope', function ($scope) {
}]);
theApp.controller('MenuSideController', ['$scope', 'CategoryService',
function ($scope, CategoryService){
CategoryService.getList()
.success(function(list){
$scope.list = list;
});
}
]);
function menuType(id) {
console.log(id);
//do something
}
HTML
<ul>
<li ng-repeat="company in list">{{ company.name }}</li>
</ul>
I'm trying to get a click method working using AngularJS but nothing works, there is no error message or even a console.log. What am I doing wrong?

The expression passed to ngClick is evaluated in the current scope. This means you have to add the function to the $scope variable in the controller:
theApp.controller('MenuSideController', ['$scope', 'CategoryService',
function ($scope, CategoryService){
CategoryService.getList()
.success(function(list){
$scope.list = list;
});
$scope.menuType = function(id) {
// do things here
}
}
]);

Related

Data-binding between ngInclude and ngView

I want to make a sidebar with list item that can be dynamically changed based on the settings page.
My app request settings.json via factory() and then called it in a controller. The controller will be used by settings.html (ngView) and sidebar.html (ngInclude).
The json will return Boolean value that also can be changed on setting page that contain checkbox which return true if check and false if not checked. I use ngShow on the sidebar to display/hide the list items.
How can I made the sidebar to reflect the changes as I tick the checkbox?
settings.factory.js
var settingsFactory = angular.module('settingsFactory', []);
settingsFactory.factory('SettingsFilterFactory', ['$http', function ($http) {
var settingsFactory = {};
settingsFactory.getSettings = function () {
return $http.get('app/data/settings.json');
};
return settingsFactory;
}]);
controller
var settingsControllers = angular.module('settingsControllers', ['settingsFactory']);
settingsControllers.controller('SettingsFilterController', ['$scope', '$http', 'SettingsFilterFactory', function ($scope, $http, SettingsFilterFactory) {
$scope.settings;
$scope.status;
getSettings();
function getSettings() {
SettingsFilterFactory.getSettings()
.then(function (response) {
$scope.settings = response.data;
}, function (error) {
$scope.status = 'Unable to load: ' + error.message;
});
}
}]);
app.js
var app = angular.module('app', ['ngRoute', 'settingsControllers']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/settings', {
title: 'Settings',
templateUrl: 'app/components/settings/settings.html',
controller: 'SettingsFilterController'
}).
otherwise({
redirectTo: '/home'
});
}]);
My index.html is something like this:
...
<body>
<section class="sidebar">
<div ng-include="'app/components/sidebar/sidebar.html'"></div>
</section>
<section class="content">
<div ng-view></div>
</section>
</body>
...
sidebar.html
<ul class="sidebar-menu" ng-controller="SettingsFilterController">
<li ng-show"settings.hiddenMenu">This is secret link</li>
</ul>
settings.html
...
<div class="checkbox">
<input type="checkbox" ng-model="settings.hiddenMenu" ng-true-value=true ng-false-value=false> Check this to show hidden menu
</div>
...
Try something like this (untested):
settings.factory.js
var settingsFactory = angular.module('settingsFactory', []);
settingsFactory.factory('SettingsFilterFactory', ['$http', function ($http) {
var settingsFactory = {};
settingsFactory.getSettings = function () {
return $http.get('app/data/settings.json');
};
settingsFactory.hiddenMenu= true;
settingsFactory.someOtherSetting = {};
return settingsFactory;
}]);
sidebar controller
settingsControllers.controller('SidebarController', ['$scope', '$http', 'SettingsFilterFactory', function ($scope, $http, SettingsFilterFactory) {
//do this in each controller, so that the factory becomes a property of $scope and can be seen in the HTML
$scope.settingsFactory = SettingsFilterFactory;
}
sidebar.html
<ul class="sidebar-menu" ng-controller="SidebarController">
<li ng-show"settingsFactory.hiddenMenu">This is secret link</li>
</ul>
settings.html
...
<div class="checkbox">
<input type="checkbox" ng-model="settingsFactory.hiddenMenu" ng-true-value=true ng-false-value=false> Check this to show hidden menu
</div>
...
Essentially, you are binding the settingsFactory object which is a singleton to each $scope that is provided by each controller. Each controller is able to change the property on the factory object, which is then visible in all other controllers that have injected this object.

angular js alert by click donot work

i am new to AngularJS so please forgive me this dump question.
i have error
Cannot set property 'test' of undefined
angularjs
var App = angular.module('StartModule', []);
App.controller('ModalDemoCtrl', [
function($scope) {
$scope.test = function() {
alert("12312");
}
}
]);
html
<body ng-app="StartModule">
<div ng-controller="ModalDemoCtrl">
<div ng-click="test()">11111</div>
</div>
<body>
You just miss $scope to controller's second argument:
var App = angular.module('StartModule', []);
App.controller('ModalDemoCtrl', [ $scope, function($scope) {
$scope.test = function() {
alert("12312");
}
}]);
You're missing the $scope dependency, you need to inject it in your controller :
App.controller('ModalDemoCtrl', ['$scope'
function($scope) {
That's why the $scope variable is undefined, you're not actually injecting any dependency in it.
This uses the Inline Array Annotation: https://docs.angularjs.org/guide/di

ng-repeat through an Array of Objects

I'm creating a little shoutbox with angular JS and StamPlay. Therefore I've created some 'Test Shouts' than can be accesed via an URL
In my Angular app I've created a Service to fetch the data:
app.factory('shouts', ['$http', function ($http) {
return $http.get('https://shoutbox.stamplayapp.com/api/cobject/v1/shouts').success(function (data) {
return data.data;
});
}]);
Inside my MainController I attach the data to the $scope.
app.controller('HomeController', [
'$scope',
'shouts',
function ($scope, shouts) {
$scope.shouts = shouts;
}
]);
But when I'm tyring to ng-repeat through the data[], i can't access the objects inside. I don't understand whats the problem.
<div ng-repeat="shout in shouts">
{{shout.title}}
</div>
shouts is a $promise even you do "return data.data". So you need to assign $scope.shouts when the promise resolved.
app.factory('shouts', ['$http', function ($http) {
return $http.get('https://shoutbox.stamplayapp.com/api/cobject/v1/shouts');
}]);
app.controller('HomeController', [
'$scope',
'shouts',
function ($scope, shouts) {
shouts.then(function(data) { $scope.shouts = data.data});
}
]);
Another options is to resolve shouts in you route config and inject it into the controller
$routeProvider
.when("/home", {
templateUrl: "home.html",
controller: "HomeController",
resolve: {
shout_data: shouts
}
app.controller('HomeController', [
'$scope',
'shout_data',
function ($scope, shout_data) {
$scope.shouts = shout_data;
}
]);
Did you forget to attach your controller to the HTML?
<div ng-controller="HomeController">
<div ng-repeat="shout in shouts">
{{shout.title}}
</div>
</div>
More information about ngController: https://docs.angularjs.org/api/ng/directive/ngController

Why variable is not available in controller?

I have HTML code:
<div ng-controller="ProfileLeftMenu">
<li ng-class="{'active':selectedTab == 'personal'}" ng-click="selectedTab = 'personal'" class="">Personal
</li>
</div>
And controller:
$scope.selectedTab = 'first';
if ($routeParams.page) {
ajax.get(page, function (CbData) {
$scope.selectedTab = page;
});
}
So, if do:
{{selectedTab}}
in template HTML get always: first
You need to update your $scope variable with the new $routeParams just after the change in route. For that you can listen for the$routeChangeSuccess event. Try this:
DEMO
app.js
var app = angular.module('plunker', ['ngRoute']);
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/test/:page', {
templateUrl: function(params) {
return 'pidat.html';
},
controller: 'MainCtrl'
});
}
]);
app.controller('MainCtrl', ['$scope', '$http', '$routeParams', function($scope, $http, $routeParams) {
// when controller is loaded params are empty
console.log('on controller load $routeParams', $routeParams);
$scope.name = 'World';
// only after you have transitioned to the new
// route will your $routeParams change so we
// need to listen for $routeChangeSuccess
$scope.$on('$routeChangeSuccess', function(){
console.log('on $routeChangeSuccess load $routeParams', $routeParams);
if ($routeParams.page) {
$scope.name = $routeParams.page;
}
});
}]);
So for your original example you would probably have to do something like this:
$scope.selectedTab = 'first';
$scope.$on('$routeChangeSuccess', function(){
if ($routeParams.page) {
ajax.get(page, function (CbData) {
$scope.selectedTab = page;
});
}
});
Use the angular $http service ($http.get()), not ajax.get(). Otherwise, Angular isn't aware of the change you make to the scope once the HTTP response comes and the callback is executed, unless you call $scope.$apply().

Angularjs - Calling only one of many subcontrollers/ multiple controllers

I have an index page wherein I define two controllers. I want to call one main controller always (should be rendered always) and the other is called only for specific sub URL calls. Should I make one nested within another, or I can keep them independent of each other? I don't have access to change routes or anything, only the controller.
Right now when I use the template (HTML) mentioned, it calls/renders both controllers, even though url is say /index
Only for /index/subPage, I want both controllers to be rendering.
/index
/index/subPage
HTML:
<div ng-controller="MainCtl" ng-init=initMain()>
<p> Within ctller2 {{results}} </p>
</div>
<div ng-controller="Ctller2"> <!-- should not be displayed unless /subPage/mainUrl is rendering -->
<p> Within ctller2 {{results}} </p>
</div>
JS:
app.controller('MainCtl', ['$scope', '$http', '$location', function ($scope, $http, $location) {
$http.get('xx/mainUrl').then(function(data) {
$scope.results = someDataJSON;
console.log(someDataJSON);
});
$scope.initMain = function() {
$scope.initMethods();
}
}]);
app.controller('Ctller2', ['$scope', '$http', '$location', function ($scope, $http, $location) {
// This controller gets initialized/rendered/called even when xx/mainUrl is called, and when xx/subPage/mainUrl is called too..
$http.get('xx/subPage/mainUrl').then(function(data) {
$scope.results = someDataJSON;
console.log(someDataJSON);
})
$http.get('xx/subPage').then(function(data) {
$scope.results = data.data;
console.log(data);
})
angular.element(document).ready(function () {
alert('Hello from SubCtl, moving over from main controller to here');
});
}]);
What am I doing wrong? I'm new to Angular.js
You can conditionally initiate a controller using ng-if. So you could try something like this:
<body ng-controller="MainCtrl">
<div ng-controller="ctrl1">{{hello}}</div>
<div ng-controller="ctrl2" ng-if="showCtrl2">{{hello}}</div>
</body>
and then set the value of the variable in a parent controller by checking the current url using $location.path()
var app = angular.module('plunker', []);
app.config(function($locationProvider){
$locationProvider.html5Mode(true);
});
app.controller('MainCtrl', function($scope, $location) {
$scope.showCtrl2 = ($location.path() === 'my path');
});
app.controller('ctrl1', function($scope){
$scope.hello = 'ctrl1 says hello';
});
app.controller('ctrl2', function($scope){
$scope.hello = 'ctrl2 says hello';
});
But it's a bit hacky and for a larger project a more robust solution would require using something like ui.router.

Resources