Getting controller name from $parent in AngularJS - javascript

I have converted one of my Angular controllers to Controller As syntax, but I am having trouble getting an ng-grid template to play nicely.
The controller has a function called edit user that looks like this
self.editUser = function (user_data) {
var modalInstance = $modal.open({
templateUrl: '/admin/views/adminuser.html',
controller: 'AdminUserController',
resolve: {
user_data: function () {
return user_data;
}
}
});
modalInstance.result.then(function () {
self.myQueryData.refresh = !self.myQueryData.refresh;
});
};
the ng-grid template looks like this
<div class="ngCellText" ng-class="col.colIndex()">
<a ng-click="$parent.$parent.$parent.$parent.editUser({user_id:row.entity.id, first_name:row.entity.first_name, last_name:row.entity.last_name, email:row.entity.email})">
<span ng-cell-text translate>Edit</span>
</a>
</div>
and my route looks like this
.when('/admin/settings', {
templateUrl: '/admin/views/settings.html',
controller: 'SettingsController as sc',
})
So the problem is in the template when I call
$parent.$parent.$parent.$parent.editUser
it doesn't know what I am talking about unless I include the controller name like
$parent.$parent.$parent.$parent.sc.editUser,
then it works great. However I don't want to bind this template directly to the sc controller. How can I call the editUser without using the controller name?
I was hoping there would be a function on the $parent that would supply the function name like
$parent.$parent.$parent.$parent.getController().editUser
Any suggestions?

You can call functions on parent scope directly without referring to $parent. Because you might get in to trouble later when you modify your view structure.
example:
<div ng-app="MyApp">
<div ng-controller="MyController">
{{myMessage}}
<div ng-controller="MyController2">
<div ng-controller="MyController3">
<div ng-controller="MyController4">
<button id="myButton" ng-click="setMessage('second')">Press</button>
</div>
</div>
</div>
<script>
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = "First";
$scope.setMessage = function(msg) {
$scope.myMessage = msg;
};
}).controller('MyController2', function($scope) {
}).controller('MyController3', function($scope) {
}).controller('MyController4', function($scope) {
});
</script>
</div>
</div>
Or else you can use angular $broadcast

Since you are using controllerAs syntax, you can address your controller by the alias, so the actual template line will look like this:
<a ng-click="sc.editUser({user_id:row.entity.id, first_name:row.entity.first_name, last_name:row.entity.last_name, email:row.entity.email})">

Related

Javascript inside a Angular router

I have build a very basic Angular Router. But now that I want to interact with my elements inside that templateUrl, no javascript gets executed or those elements inside the templateUrl can not be accessed. I have copied the most of the code from this instruction, here.
My index file:
<html ng-app="myApp">
<head></head>
<body ng-controller="mainController">
<a id="btnHome" href="#/">Startseite</a>
<a id="btnPlanner" href="#/planner">LTC-Planner</a>
<a id="btnSocial" href="#/social">LTC-Social</a>
<div id="main">
<!-- angular content -->
<div ng-view></div>
</div>
<script src="js/routing.js"></script>
</body>
</html>
This is my routing.js file:
// Create the angular module
var myApp = angular.module('myApp', ['ngRoute']);
// Configure our routes
myApp.config(function($routeProvider) {
$routeProvider
// Route for the home page
.when('/', {
templateUrl: 'pages/home.html',
controller: 'mainController'
});
});
// Create the controller and inject angular's $scope
myApp.controller('mainController', function($scope) {
$scope.message = 'This is the HOME page';
});
and this is the template file located at pages/home.html:
<button id="btnTest">Say Hello</button>
<script>
var btnTest = document.getElementById('btnTest');
btnTest.addEventListener('click', function(){
console.log('Hello');
});
</script>
maybe one of you got an idea or has seen an alternative.
Thanks,
André
you should try to wrap your html template in a single tag
<div>
<button ng-click="test()">Say Hello</button>
</div>
And remove the script to put the logic inside your controller. Since your using angular, just use ng-click to bind click listener.
myApp.controller('mainController', function($scope) {
$scope.message = 'This is the HOME page';
$scope.test = function() {
console.log('Hello');
}
});

How to render HTML Tags from ngModel?

I'm using AngularJS for binding JS variables to my HTML content, and it works fine.
JS
var app = angular.module("Tabs", [])
.controller("TabsController", ['$scope', function($scope){
$scope.events = my_JS_object;
})
HTML
<div>{{events.test}}</div>
It works as long as my_JS_object.test is a simple string, like "Hello World", but once I try to put HTML tag in there, such as Hello <b>World</b> It doesn't use the tags as HTML elements, but as simple text. Which makes sense, only I have no idea how to make the HTML tags work.
As stated by Angular documentation, you can use inbuilt ng-bind-html directive to evaluate model string and insert resulting HTML into element.
Example:
If you have model value like:
$scope.myHTML =
'I am an <code>HTML</code>string with ' +
'links! and other <em>stuff</em>';
Use ng-bind-html like:
<p ng-bind-html="myHTML"></p>
For detailed information go through: https://docs.angularjs.org/api/ng/directive/ngBindHtml
Note: Don't forget to inject ngSanitize service in your app.
You need to use the ngBindHtml directive that properly evaluates the expression and inserts the resulting HTML into the element in a secure way. To do this, you must include a reference to angular-sanitize.js in your HTML and then in your angular module, inject ngSanitize.
Like so
var app = angular.module("Tabs", ['ngSanitize'])
.controller("TabsController", ['$scope', function($scope){
$scope.events = my_JS_object;
})
<div ng-controller="TabsController">
<div ng-bind-html="events.test"></div>
</div>
Here is a full working example:
(function(angular) {
'use strict';
angular.module('bindHtmlExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.myHTML = 'Hello This is <b>BOLD<b/>';
}]);
})(window.angular);
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular-sanitize.js"></script>
</head>
<body ng-app="bindHtmlExample">
<div ng-controller="ExampleController">
<p ng-bind-html="myHTML"></p>
</div>
</body>
Refer to the official angular documentation for details:
https://docs.angularjs.org/api/ng/directive/ngBindHtml
If you want to insert HTML into page you shouldn't do it this way.
There is sanitize for this task.
For example in your controller:
$scope.trustedHtml = "<b>Hello World</b>"
And in your html:
<div ng-bind-html="trustedHtml "></div>
Always check html if using a user given text before inserting.
Also don't forget to add ngSanitize as dependency while creating controller
It's easier to use transclusion if you want to embed custom HTML into your DOM tree.
angular.module('myApp', [])
.controller('MainCtrl', function ($scope) {
$scope.overwrite = false;
$scope.origin = 'parent controller';
})
.directive('myDirective', function() {
return {
restrict: 'E',
templateUrl: 'my-directive.html',
scope: {},
transclude: true,
link: function (scope) {
scope.overwrite = !!scope.origin;
scope.origin = 'link function';
}
};
});
<script src="https://code.angularjs.org/1.3.2/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MainCtrl">
<my-directive>
<p>HTML template</p>
<p>Scope from {{origin}}</p>
<p>Overwritten? {{overwrite}}</p>
</my-directive>
</div>
<script type="text/ng-template" id="my-directive.html">
<ng-transclude></ng-transclude>
<hr />
<p>Directive template</p>
<p>Scope from {{origin}}</p>
<p>Overwritten? {{overwrite}}</p>
</script>
</div>

ng-include with a variable for src

I would like to change the ng-includes src with a variable. Currently this is what I have.
<div class='alignRightCenter' id='rightContent'>
<ng-include src="'{{view}}'"> </ng-include>
</div>
And here is the controller:
ctrl.controller('contentCtrl', ['$scope', function($scope) {
$scope.view = "partials/setListName.tpl.html";
}]);
Unfortunately I can not use a ng-view because it is already being used to get me to this page.
Is it possible to make something like this work?
Try as follows:
<ng-include src="view"> </ng-include>
-----------------OR----------------------
You can do this way,
View:
<div data-ng-include data-ng-src="getPartial()"></div>
Controller:
function AppCtrl ($scope) {
$scope.getPartial = function () {
return 'partials/issues.html';
}
}
Like this. You need to use single quotes and +, like you would in JavaScript.
<ng-include src="'/path/to/template'+ my.variable +'.html'"></ng-include>

Call parent controllers' function from directive in angular

jsfiddle
I have a ng-click within a directive named ball. I am trying to call MainCtrl's function test() and alert the value of ng-repeat's alignment of ball.
Why cant i recognize the MainCtrl's test function?
var $scope;
var app = angular.module('miniapp', []);
app.controller('MainCtrl', function($scope) {
$scope.project = {"name":"sup"};
$scope.test = function(value) {
alert(value);
}
$scope.test2 = function(value) {
alert('yo'+value);
}
}).directive('ball', function () {
return {
restrict:'E',
scope: {
'test': '&test'
},
template: '<div class="alignment-box" ng-repeat="alignment in [0,1,2,3,4]" ng-click="test(alignment)" val="{{alignment}}">{{alignment}}</div>'
};
});
html
<div ng-app="miniapp">
<div ng-controller="MainCtrl">
{{project}}
<ball></ball>
</div>
</div>
You need to pass the test() method from the controller into the directive...
<div ng-app="miniapp">
<div ng-controller="MainCtrl">
{{project}}
<ball test="test"></ball>
</div>
</div>
Change & to = in directive:
scope: {
'test': '=test'
}
Fiddle: http://jsfiddle.net/89AYX/49/
You just need to set the controller in your directive as:
controller: 'MainCtrl'
so the code for your directive should look like:
return {
restrict:'E',
scope: {
'test': '&test'
},
template: '<div class="alignment-box" ng-repeat="alignment in [0,1,2,3,4]" ng-click="test(alignment)" val="{{alignment}}">{{alignment}}</div>',
controller: 'MainCtrl'
};
the one way is to not isolate a directive scope...just remove the scope object from directive.
Another way is to implement an angular service and put a common method there, inject this service wherever you need it and in the directive call function that will be insight isolated scope and there call a function from directive

Angularjs filter search from outside the ng-view [duplicate]

I have a setup with an ng-view (an admin panel) that lets me display orders. I have a search box outside of ng-view that I would like to use to modify my json request. I've seen some posts on accessing things such as the title but was not able to get them to work - perhaps outdated.
Main app stuff:
angular.module('myApp', ['myApp.controllers', 'myApp.filters', 'myApp.services', 'myApp.directives', 'ui.bootstrap']).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: '/partials/order/manage.html',
controller: 'ManageOrderCtrl'
}).
when('/order/:id', {
templateUrl: '/partials/order/view.html',
controller: 'ViewOrderCtrl'
}).
otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
}]);
Manage controller:
angular.module('myApp.controllers', [])
.controller('ManageOrderCtrl', ['$scope', '$http', '$dialog', 'config', 'Page', function($scope, $http, $dialog, config, Page) {
// would like to have search value from input #search available here
var getData = function() {
$http.get('/orders').
success(function(data, status, headers, config) {
$scope.orders = data.orders;
});
};
getData();
})
View:
<body ng-app="myApp" >
<input type="text" id="search">
<div class="ng-cloak" >
<div ng-view></div>
</div>
</body>
If you're going to access stuff outside the <div ng-view></div>, I think a better approach would be to create a controller for the outer region as well. Then you create a service to share data between the controllers:
<body ng-app="myApp" >
<div ng-controller="MainCtrl">
<input type="text" id="search">
</div>
<div class="ng-cloak" >
<div ng-view></div>
</div>
</body>
(ng-controller="MainCtrl" can also be placed on the <body> tag - then the ng-view $scope would be a child of the MainCtrl $scope instead of a sibling.)
Creating the service is as simple as this:
app.factory('Search',function(){
return {text:''};
});
And it's injectable like this:
app.controller('ManageOrderCtrl', function($scope,Search) {
$scope.searchFromService = Search;
});
app.controller('MainCtrl',function($scope,Search){
$scope.search = Search;
});
This way you don't have to rely on sharing data through the global $rootScope (which is kinda like relying on global variables in javascript - a bad idea for all sorts of reasons) or through a $parent scope which may or may not be present.
I've created a plnkr that tries to show the difference between the two solutions.
You can use scope hierarchies.
Add an "outer" ng-controller definition to your HTML like this:
<body ng-controller="MainCtrl">
It will become the $parent scope. But you do not need to share data by using a service. You don't even need to use the $scope.$parent scope. You can use scope hierarchies. (See the Scope Hierarchies section on that page). It is really easy.
In your MainCtrl, you may have this:
$scope.userName = "Aziz";
Then in any controller that is nested within MainCtrl (and does not override the userName in its own scope) will have userName also! You can use in in the view with {{userName}}.
Try this...
View:
<body ng-app="myApp" >
<input type="text" id="search" ng-model="searchQuery" />
<div class="ng-cloak" >
<div ng-view></div>
</div>
</body>
Using it in your controller:
$http.get('/orders?query=' + $scope.searchQuery).
success(function(data, status, headers, config) {
$scope.orders = data.orders;
});
Basically, you can do that with anything INSIDE ng-app... Move your ng-app to the html tag and you can edit the title as well!

Categories

Resources