ng-click(s) does not work in partial view - angularjs

I'm trying to render partial view on click, which has controller in it.
Layout/Index page :
<!DOCTYPE html>
<html lang="en" ng-app="AngularDemo">
<head>
..
</head>
<body>
<aside>
<ul class="nav nav-list" ng-controller="Navigations as nav">
<li class="">Home</li>
<li class=""> Feedbacks</li>
</ul>
</aside>
<section id="MainBody"></section>
</body>
</html>
controller.js
myApp.controller("Navigations", ["$compile", function ($compile) {
var $this = this;
this.showFeedbackDiv = function ($event) {
var compiledeHTML = $compile("<div load-Div></div>")($this);
$("#MainBody").append(compiledeHTML);
$(".Division").hide();
$("." + $(event.currentTarget).data("thisdiv")).show();
};
}]).directive('loadDiv', function () {
return {
templateUrl: '/Default/GetFeedbackView',
controller: 'Feedback'
};
});
myApp.controller("Feedback", ['AngService', '$element', function(AngService, $element) {
this.feedbackData = {};
var $this = this;
this.ShowFeedbacks = function () {
AngService.ShowFeedbacks().then(function (response) {
$this.allFeedbacks = JSON.parse(response.data);
console.log($this.allFeedbacks);
$("#ShowFeedbacksModal").modal({ backdrop: 'static', keyboard: false, show: true });
}, function (response) {
alert('Error in getting feedbacks');
});
};
}]);
partial View :
<div class="Division FedbackDiv" style="margin-top:40px" ng-controller="Feedback as fb">
<div class="page-header">
<h1>
Feedback form
<span style="cursor:pointer;" class="pull-right" ng-click="fb.ShowFeedbacks()"><i class="fa fa-adn"></i></span>
</h1>
</div>
<div class="row">
...
</div>
</div>
When i click on "show Feedbacks" nothing happens
error :
TypeError: a.$new is not a function
at g (angular.js:6970)
at M (angular.js:7618)
at angular.js:7854
at angular.js:12914
at h.$eval (angular.js:14123)
at h.$digest (angular.js:13939)
at h.$apply (angular.js:14227)
at p (angular.js:9493)
at J (angular.js:9678)
at XMLHttpRequest.t.onload (angular.js:9621)(anonymous function) # angular.js:11358

Should pass $scope in $compile; $scope should be injected into the controller; if you inspect the object this, it's not scope
instead of
var compiledeHTML = $compile("<div load-Div></div>")($this);
try
var compiledeHTML = $compile("<div load-Div></div>")($scope);
To inject $scope
myApp.controller('Navigations', ['$compile', '$scope', function ($compile, $scope) { ... }])

remove ng-controller="Feedback as fb from partial and add controllerAs : fb to loadDiv config
.directive('loadDiv', function () {
return {
templateUrl: '/Default/GetFeedbackView',
controller: 'Feedback',
controllerAs : 'fb'
};

Related

Get data from directive and change image according to data value

I want to get the value of current.flag from my template property in random.js file and use it after in my HTML file. According to the value of flag I will receive, I would like an image to be changed. I would like some help for that, because I'm beginner to Angular.
Thanks in advance
<section class="has-header">
<div class="container">
<div class="row">
<div class="col-md-4 text-center">
<img ng-src="{{current.flag === 'gr' ? 'images/image_1.png' : 'images/image_2.png'}}" />
</div>
</div>
</div>
</section>
random.js
angular.module('app')
.directive('language', function () {
return {
restrict: 'E',
replace: true,
scope: {},
template: '<div class="languages-wrap pull-right">\
<div class="languages f32">\
<div ng-click="poped=!poped" class="current flag {{current.flag}}"></div></div>\
<div class="language-selector" ng-show="poped">\
<ul class="languages-list">\
<li ng-repeat="l in langs">\
<a ng-click="changeLang(l)" class="languages f32">\
<div class="flag {{l.flag}}"></div>\
</a>\
</li>\
</ul>\
</div>\
</div>',
controller: ['$scope', '$cookies', '$translate', '$route', '$location',
function ($scope, $cookies, $translate, $route, $location) {
$scope.poped = false;
$scope.langs = [
{
iso: 'el',
flag: 'gr'
},
{
iso: 'en',
flag: 'us'
}
];
$scope.current = $cookies.getObject('lang') ? $cookies.getObject('lang') : $scope.langs[0];
$scope.changeLang = function (lang) {
$cookies.putObject('lang', lang, {expires: new Date(2020, 10, 10)});
$translate.use(lang.iso);
$scope.current = lang;
$scope.poped = false;
$location.search('lang', lang.iso);
$route.reload();
};
}
]
};
});
u can do a controller to the html file and add
$scope.current = $cookies.getObject('lang') ? $cookies.getObject('lang') : $scope.langs[0];
to the controller
if i understand correctly , u want to use the $scope.current value from a directive in another html file, which is not connected to the directive , if yes , what u can do is add a controller to this html and add the
$scope.current = $cookies.getObject('lang') ? $cookies.getObject('lang') : $scope.langs[0];
to it How to bind an AngularJS controller to dynamically added HTML?
make controller file
add it to index.html,
add this inside it
var app = angular.module('myApp', []);
app.controller('exampleCtrl', function($scope, $cookies) {
$scope.current = $cookies.getObject('lang') ? $cookies.getObject('lang') : $scope.langs[0];
});
in the html add controller to the section tag
<section class="has-header" ng-controller="exampleCtrl">

Scope doesn't work

I'd like to set a scope for a different route but it seems not working...
var app = angular.module('AngularApp', ['ngRoute', 'ngAnimate']);
app.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'menu.html',
controller: 'MenuController'
}).when('/slides/:menuItem', {
templateUrl: 'slides.html',
controller: 'SlidesController'
});
});
app.controller('MenuController', function($scope, $http) {
$http.get('database.json').then(function(response) {
$scope.bottomBar = 'no';
$scope.pageClass = 'menus';
$scope.database = response.data;
});
});
app.controller('SlidesController', function($scope, $http, $routeParams) {
$http.get('database.json').then(function(response) {
$scope.bottomBar = 'yes';
$scope.pageClass = 'slides';
$scope.database = _.find(response.data.menuItems, {'url': $routeParams.menuItem});
});
});
<body ng-app="AngularApp">
<div class="line">
<div class="col-12">
<img src="images/logo.jpg">
</div>
</div>
<div class="page {{pageClass}}" ng-view></div>
<div class="bottom-bar">
<ul>
<li>Retour {{bottomBar}}</li>
</ul>
</div>
</body>
bottomBar is empty...
Looks like you are putting html in app directly.
You can move below code in a template and use ng-include to add this template in you all views.
<div class="bottom-bar">
<ul>
<li>Retour {{bottomBar}}</li>
</ul>
</div>
This is because your controller scope is present in this div with ngView. Therefore anything outside this div won't have scope binding.
<div class="page {{pageClass}}" ng-view></div> <!-- controller active here only -->

Not able to open modal box selecting value from the dropdown using ui-bootstrap-tpls.min.js and angular.min.js

Changing the value from the dropdown trying to open the modal and supposed to perform http request and body of will be filled with the response. But unable to open the modal. Any help will be really appreciated.
<head>
<title>Hello AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.min.js"></script>
<link href="bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller='NodeProvision'>
<select ng-model="nodes" ng-change="nodeprovision(nodes)">
<option value="">please select</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Welcome to modal!!</h3>
</div>
<div class="modal-body">
<ul>
//<div ng-if="test">
<p>The response is {{items}} <span ng-bind="{{items}}"></span><i ng-hide="items" class="icon icon-refresh icon-spin">loading.........</i></p>
//</div>
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
<!-- <div ng-if="test">
<p>The response is {{response}} <span ng-bind="{{response}}"></span><i ng-hide="response" class="icon icon-refresh icon-spin">loading.........</i></p>
</div> -->
</div>
</body>
<script>
//Initializing the app
var app = angular.module('myApp',['ui.bootstrap']);
//Defining the controller to perform the business logic
app.controller('NodeProvision', ['$scope','$http','$modal', function($scope,$http,$modal) {
$scope.nodeprovision = function(node){
$scope.animationsEnabled = true;
$scope.open = function (size) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
$http.get('http://ac-00075763.devapollogrp.edu:8080/NodeProvision/provision/urn:apol:provider:acp/list?guid=5d4dc79e-f623-40f8-a14f-646c59c7b89a').
success(function(data, status, headers, config) {
$scope.items = data
}).
error(function(data, status, headers, config) {
// log error
});
}
}
});
};
}
}]);
app.controller('ModalInstanceCtrl', function ($scope, $modalInstance, items) {
$scope.items = items;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
</script>
</html>
Plunker Demo
Here is a fairly straightforward version of what you're trying to do. I have used a service (which would normally get the records using an $http request) in the resolve to keep things nice and clean.
Importantly, you should note the use of the return in the resolve objects. Without these, there is nothing to signal to the resolve that everything is done and it can allow the modal.open to do it's thing! Here's a great tutorial on using resolve with routes. The resolve property in the $modal service works identically to the one in ngRoute.
app.controller('ModalDemoCtrl', function ($scope, $modal, Data) {
$scope.animationsEnabled = true;
$scope.open=function(){
var modalInstance=$modal.open({
animation: true,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
resolve: {
loaddata: function(Data) {
return Data.get('allrecords');
},
selected: function () {
return $scope.model.id;
}
}
});
};
});
app.controller('ModalInstanceCtrl', function ($scope, $modalInstance, selected, loaddata) {
$scope.allrecords = loaddata.records;
$scope.selected = selected;
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});

AngularJS $scope.$parent strange hierarchy

I'm trying to access the $parent in my child controller but for some reason I have to access the Fifth $parent in order to get the actual $scope from the Parent controller, Any Ideas?
Parent Controller
angular.module('App')
.controller('HomeController', ['$scope', '$rootScope', 'user',
function($scope, $rootScope, user) {
$rootScope.currentNav = 'home';
$rootScope.currentUser = user.data;
$scope.tabs = [
{
heading : 'Empresas',
template : 'home_companies_tab.html'
},
{
heading : 'Tickets',
template : 'home_tickets_tab.html'
}
];
$scope.companies = []
$scope.selectedCompanyIndex = undefined;
$scope.selectedCompany = undefined;
$scope.selectedTicketIndex = undefined;
$scope.selectedTicket = undefined;
}]);
Child Controller
angular.module('App')
.controller('HomeCompaniesTabController', ['$scope', 'Companies',
function($scope, Companies) {
$scope.loadCompanies = function () {
$scope.companies = Companies.query();
}
/**
* Init
*/
$scope.selectCompany = function (company, index) {
$scope.$parent.selectedCompanyIndex = index; //this doesnt work
$scope.$parent.$parent.$parent.$parent.$parent.selectedCompany = company; //this does, why?
console.log($scope);
}
if($scope.currentUser.security < 3) {
$scope.loadCompanies();
}
}]);
Home template
<div ng-include="'dist/templates/header.html'"></div>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
company : {{selectedCompany}}
</div>
</div>
<tabset>
<tab ng-repeat="tab in tabs" heading="{{tab.heading}}">
<div ng-include="'dist/templates/' + tab.template" ></div>
</tab>
</tabset>
</div>
Child template
<div class="row-fluid" ng-controller="HomeCompaniesTabController">
<div class="col-md-3">
<h4>Lista de Empresas</h4>
<hr/>
<div class="list-group">
<a
href=""
class="list-group-item"
ng-repeat="company in companies"
ng-click="selectCompany(company, $index)">
<h4 class="list-group-item-heading">
{{company.name}}
</h4>
</a>
</div>
</div>
<div class="col-xs-9">
<div ng-show="selectedCompany">
<h4><b>{{selectedCompany.name}}</b></h4>
</div>
</div>
Based on the comments of charlietfl I came up with this simple service for sharing data
angular.module('App')
.factory('SharedData', [function () {
return {
}
}]);
Then I simply inject it in the controllers
angular.module('App')
.controller('HomeController', ['$scope', '$rootScope', 'user', 'SharedData',
function($scope, $rootScope, user, SharedData) {
$rootScope.currentNav = 'home';
$rootScope.currentUser = user.data;
$scope.sharedData = SharedData;
$scope.tabs = [
{
heading : 'Empresas',
template : 'home_companies_tab.html'
},
{
heading : 'Tickets',
template : 'home_tickets_tab.html'
}
];
$scope.companies = [];
}]);

Why does $modal introduce an extra scope for the form?

I've managed to use the example from angular-ui-bootstrap to demonstrate the problem (but you need the console open to see it) Plnkr link to this code
Why is the form being stuck in a sub scope instead of this $scope?
The HTML
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="ModalDemoCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>I'm a modal!</h3>
</div>
<div class="modal-body">
<ng-form name="myForm">
<ul>
<li ng-repeat="item in items">
<a ng-click="selected.item = item">{{ item }}</a>
</li>
</ul>
Selected: <b>{{ selected.item }}</b>
</ng-form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
<button class="btn btn-default" ng-click="open()">Open me!</button>
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
</body>
</html>
** The Javascript **
angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
};
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.
var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
console.log("The form in the $scope says: ", $scope.myForm);
console.log("The form in the $scope.$$childTail says: ", $scope.$$childTail.myForm);
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
The ng-form is not in the $scope where I would expect it to be, even though the other $scope items are there. What is the cause of the nested scope for the form (that is added by angular for form validation).
The output from the console looks like:
The form in the $scope says: undefined example.js:37
The form in the $scope.$$childTail says:
Constructor {$error: Object, $name: "myForm", $dirty: false, $pristine: true, $valid: true…}
If you do not specify a scope property on $modal.open it take $rootscope. This is from documentation
scope - a scope instance to be used for the modal's content (actually
the $modal service is going to create a child scope of a provided
scope). Defaults to $rootScope
so set scope before call
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
scope:$scope,
resolve: {
items: function () {
return $scope.items;
}
}
});
If you want to access the $scope declared on your main controller and make it accessible to the modal you have to include in your modal configuration.
scope: $scope
Just like what Chandermani put up on his answer above.
This is because transclusion used in modals which creates new scope for form. I am defining forms this way:
<form name="$parent.myForm">
Then you can use $scope.myForm in modal controller.

Resources