I've a strange behavior using multiple transclude component in Angularjs:
changes in first slot model no visible in controller.
<div ng-app="myApp" ng-controller="testController">
<script type="text/ng-template" id="component-template.html">
<div style="color:red;" ng-transclude="heading">
</div>
<div style="color:blue;" ng-transclude="body">
</div>
</script>
Example1
<input ng-model="example1Model"/>
<test-component>
<panel-heading>
Example2
<input ng-model="example2Model"/>
</panel-heading>
<panel-body>
Example1Result:{{example1Model}}<br/>
Example2Result:{{example2Model}}
</panel-body>
</test-component>
</div>
<script>
angular.module("myApp", [])
.controller("testController", function ($scope, $location) {
})
.component("testComponent", {
templateUrl: "component-template.html",
transclude: {
heading: "panelHeading",
body: "panelBody"
},
controller: function ($scope, $element, $attrs) {
this.$doCheck = function () {
//do anything
}
}
});
</script>
Now if you try to test it in this JSfiddle:https://jsfiddle.net/Lpveophe/1/
Why binding model example2Model did not working?
However example1Model binding model working correctly.
You need to use . in ng-model to make it work. For better understand of scope, please go through this article: https://github.com/angular/angular.js/wiki/Understanding-Scopes
To make it work, replace example2Model with o.example2Model everywhere and change your controller to:
.controller("testController", function ($scope, $location) {
$scope.o = {};
$scope.o.example2Model = '';
})
Related
I'm trying to get an Angular Bootstrap UI Modal (0.14) working. I can get the modal to pop up (great) but the data object I'm passing is null (it isn't null when i set it). I've looked at all sorts of plukners, which I see how they work, mine just doesn;t seem to work.
Below, I've rigged it to pass some made up data, in
(function () {
'use strict';
angular.module('MPAapp')
.controller('workCentreCtrl',
['$scope', '$rootScope', 'toastrFactory', 'workCentreResource', '$uibModal', '$log',
workCentreCtrl])
function workCentreCtrl($scope, $rootScope, toastrFactory, workCentreResource, $uibModal, $log) {
var scope = this;
var slot = [{'slot1':5}, {'slotname':'dynamo'},{'OriginalSlot':5}]
var max = 5
// Click event from the view
$scope.EditWorkOrder = function () {
var modalInstance = $uibModal.open({
animation: true,
templateUrl: '/app/WorkOrder/Views/EditWorkOrder.html',
controller: 'EditWorkOrderCtrl',
size: 'lg',
resolve: {
data: function () {
return{
Slot: slot,
Max: max
}
}
}
});
modalInstance.result.then(function () {
$log.info('do some UI update here');
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
}
}());
/* END PARENT CONTROLLER */
/* --------------------------------*/
/* MODAL INSANCE CONTROLLER BEGIN*/
(function () {
'use strict';
angular.module('MPAapp')
.controller('EditWorkOrderCtrl', ['$scope', '$timeout', 'toastrFactory',
EditWorkOrderCtrl]);
EditWorkOrderCtrl.$inject = ['$uibModalInstance', 'data']
function EditWorkOrderCtrl($scope, $timeout, toastrFactory, $uibModalInstance, data) {
var scope = this;
$scope.ok = function () {
$uibModalInstance.close(scope.Slot);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
// THIS IS WHEN DATA IS UNDEFINED.
scope.Slot = data.Slot;
scope.SlotNumber = data.Slot.OriginalSlot;
}
}());
And the HTML in the modal instance
<div ng-controller="EditWorkOrderCtrl as vm">
<div class="row">
<div class="col-md-12">
<h2>Edit Work Order {{vm.Slot.WorkOrderNumber}}</h2>
</div>
</div>
<div class="row">
<div class="col-md-12"><span class="main-text bold">Product:</span> {{vm.Slot.ProductCode}} - {{vm.Slot.ProductDescription}}</div>
</div>
<div class="row">
<div class="col-md-6">
<span class="main-text bold">Size:</span> {{vm.Slot.QuantityRequired}}
<span class="main-text bold">Time (mins):</span> {{vm.Slot.StandardRunTime}}
<span class="main-text bold">Current Date:</span>{{vm.Slot.OriginalOrderDate | date:'dd MMM yyyy'}}
</div>
<div class="col-md-6"></div>
</div>
</div>
Any help very much appreciated. I'm still quite new to Angular, it's proving a tough nut in some areas, but I love it!
Of course data is not going to be available like this (but it's not null, it's undefined). Your dependency injection is messed up. Note, that what you are describing in $inject array, must correspond to formal parameters passed to controller function.
In your case with this configuration:
EditWorkOrderCtrl.$inject = ['$uibModalInstance', 'data']
function EditWorkOrderCtrl($scope, $timeout, toastrFactory, $uibModalInstance, data) {}
you tell Angular to inject $uibModalInstance as $scope, and data as $timeout. Clearly not what you want.
Correct injection should look like
EditWorkOrderCtrl.$inject = ['$scope', '$timeout', 'toastrFactory', '$uibModalInstance', 'data'];
function EditWorkOrderCtrl($scope, $timeout, toastrFactory, $uibModalInstance, data) {}
Alternatively you can use array notation as controller definition:
.controller('EditWorkOrderCtrl', ['$scope', '$timeout', 'toastrFactory', 'workCentreResource', 'blockedDatesResource', 'data', EditWorkOrderCtrl]);
but in this case make sure you don't use EditWorkOrderCtrl.$inject = ['$uibModalInstance']. Remove it because it has higher priority and as I explained above it's messed up.
Also take a look at this answer, where I provided detail explanation about different injection methods.
I have school task.
We have a HTML code like this:
<html ng-app="myTest">
<head><script type="text/javascript" src="../myScript.js"></script>
</head>
<body id="tst" class="textpage" ng-controller="TestController as testcon">
<form class="" id="frm" ng-submit="doStuff()">
<div class="form-group">
{{testinfo}}
</div>
<div class="form-group">
<button type="submit" id="sbtn" name="sbtn">testSubmit</button>
</div>
</form>
</body>
</html>
Content of javascript with name myScript.js is this:
var tester = angular.module('myTest', ['ui.mask']);
tester.controller('TestController', ['$scope', '$http', '$location', '$window', function ($scope, $http, $location, $window) {
$scope.doStuff = function () {
{
$scope.testinfo = 'unknown value';
};
};
}
]);
I have option to add new javascript.
But I am not possible to get value from $scope.testninfo.
I cannot edit existing JavaScript and cannot edit HTML file. I can just add new javascript.
Is there option how to get value from $scope.testinfo in another javascript?
Thanks.
You can use broadcast
From controller 1 we broadcast an event
$scope.$broadcast('myEvent',anyData);
controller 2 will receive our event
$scope.$on('myEvent', function(event,anyData) {
//code for controller 2
});
here anyData represent your object to be passed
Use ng-model.
<div class="form-group">
<input type="text" ng-model="testinfo">
</div>
I dont think it is possible without appending the existing javascript/html. Because the $scope of the TestController cannot be accessed from another controller (file).
If you COULD append the HTML you could use the $rootscope, in that way the value, which is set by the TestController is accessible from another controller. Or you can add a Global app value. I created a fiddle which show the two options: https://jsfiddle.net/Appiez/wnyb9pxc/2/
var tester = angular.module('myTest', []);
tester.value('globalVar', { value: '' });
tester.controller('TestController', ['$rootScope', '$scope', '$http', '$location', '$window', 'globalVar', function ($rootScope, $scope, $http, $location, $window, globalVar) {
$scope.doStuff = function () {
{
$rootScope.testinfo = 'this is the new value';
globalVar.value = 'a global value';
};
};
}
]);
tester.controller('TestController2', ['$rootScope', '$scope', 'globalVar', function ($rootScope, $scope, globalVar) {
$scope.doStuff2 = function () {
{
alert($rootScope.testinfo);
alert(globalVar.value);
};
};
}
]);
This is what services are for in angular. They ferry data across controllers. You can use NG's $broadcast to publish events that contain data, but Providers, Services, and Factories are built to solve this.
angular.module('krs', [])
.controller('OneCtrl', function($scope, data){
$scope.theData = data.getData();
})
.controller('TwoCtrl', function($scope, data){
$scope.theData = data.getData();
})
.service('data', function(){
return {
getData: function(){
return ["Foo", "Bar"];
}
}
});
Here's a fiddle to help get you into the swing of things. Good luck in school!
I am trying to add another AngularJS directive to my app but for some reason it is not working. I have added other directives before in the same way but they are all working. I have posted code below.
HTML where I include the directive
<section class="section-wrap" data-ng-controller="PVProfileViewController">
<div class="container bg_white">
<div>
<pv-profile-password-reset pv-user="user"></pv-profile-password-reset>
</div>
<div>
<pv-profile-email-update pv-user="user"></pv-profile-email-update>
</div>
</div>
</section>
AngularJS directive file
'use strict';
/*
* The profile email request update section
*/
angular.module('mean.system').directive('pvProfileEmailUpdate',
['PVProfile', '$timeout', 'Global', 'Utilities',
function (PVProfile, $timeout, Global, Utilities)
{
function controller($scope)
{
$scope.global = Global;
$scope.darkout = false;
}
function link(scope, element, attrs)
{
}
return {
restrict: 'E',
templateUrl: '/path/to/profile_email_update.html',
link: link,
scope: {
user: '=pvUser'
},
controller: controller
};
}
]
);
Any ideas why this specific directive would not be working but others very similar to it would be?
Generally, what I want to do, is to initialize nested ng-controller inside ng-repeat using variable.
JSFiddle
JS
angular.module('app',[])
.controller('main',function($scope){
angular.extend($scope,{
name:'Parent Controller',
items:[
{name:'nested2'},
{name:'nested1'}
]
});
})
.controller('nested1',function($scope){
$scope.name = "Name1";
})
.controller('nested2',function($scope){
$scope.name = "Name2";
});
I want this:
<div ng-controller="main" ng-app='app'>
Nested: {{name}}
<div ng-controller="nested1">{{name}}</div>
<div ng-controller="nested2">{{name}}</div>
</div>
to become to something like this:
<div ng-controller="main">
Nested: {{name}}
<div ng-repeat="item in items">
<div ng-controller="item.name">{{name}}</div>
</div>
</div>
Problem: it does not work this way. Neither it works any other way, that I've tried after google'ing for an hour or so.
Is there any "legal" and nice way to achieve that at all?
There isn't a real way,using angular features it at this point, i suppose. You could create a directive and use un-documented dynamic controller feature controller:'#', name:'controllerName'. But this approach will not evaluate bindings or expressions that provide the controller name. What i can think of is a hack by instantiating a controller provided and setting it to the element.
Example:-
.directive('dynController', function($controller){
return {
scope:true, //create a child scope
link:function(scope, elm, attrs){
var ctrl =scope.$eval(attrs.dynController); //Get the controller
///Instantiate and set the scope
$controller(ctrl, {$scope:scope})
//Or you could so this well
//elm.data('$ngControllerController', $controller(ctrl, {$scope:scope}) );
}
}
});
And in your view:-
<div ng-controller="main">
<div ng-repeat="item in items">
Nested:
<div dyn-controller="item.name" ng-click="test()">{{name}}</div>
</div>
</div>
Demo
Note that i have changed the position of ng-controller from the element that does ng-repeat, since ng-repeat (1000) has higher priority than ng-controller (500), ng-repeat's scope will prevail and you end up not repeating anything.
While looking at it
Invested more couple hours into it, inspecting angular's sources etc.
The expression, given to ng-controller, is not being evaluated at all.
Here is best approach I've found:
HTML:
<div ng-controller="main">
Nested: {{name}}
<div ng-repeat="item in items">
<div ng-controller="nested" ng-init="init(item)">{{name}}</div>
</div>
</div>
JS:
angular.module('myApp', [])
.controller('main', function ($scope, $controller) {
angular.extend($scope, {
name: 'Parent Controller',
items: [
{name: 'nested2'},
{name: 'nested1'}
]
});
})
.controller('nested', function ($scope, $controller) {
angular.extend($scope, {
init: function (item) {
$controller(item.name, {'$scope': $scope});
}
});
})
.controller('nested1', function ($scope) {
$scope.name = 'test1';
})
.controller('nested2', function ($scope) {
$scope.name = 'test2';
});
I've been playing around with this bug but I can't seem to figure it out. The problem started when I pushed the angular-bootstrap models I had added to the prod server. The original error was this:
"AngularJS Error: Unknown provider: aProvider <- a"
I'm pretty sure I was getting that error because my files weren't minifying correctly. So I went through my controllers and found that I wasn't $injecting $modal instance into my controllers and that's when I ran into this problem.
Whenever I inject $modalInstance into my controller in the minified format I get this error. I am not using the format angular-bootstrap suggests because I have a lot going on and many controllers on the site I'm building so I combined everything into one controller instead of several functions.
My Controller:
.controller('CreateGroupCtrl', ['$scope', '$http', '$window', '$cookies', '$modal', '$log', 'FeedService', '$modalInstance',
function CreateGroupCtrl($scope, $http, $window, $cookies, $modal, $log, $modalInstance, FeedService) {
$scope.createGroupCall = function createGroupCall(teacher, name) {
if(teacher != null && name != null) {
FeedService.createGroupCall($cookies.token, $window.sessionStorage.user, teacher, name).success(function(data) {
console.log('GroupCreated');
}).error (function(status,data,token) {
console.log(status);
console.log(data);
});
} else {
alert("Error!");
}
}
/***********ANGULAR-UI MODAL CODE**********/
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'CreateGroupContent.html',
controller: CreateGroupCtrl,
size: size
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}]);
My Template:
<button ng-controller="CreateGroupCtrl" ng-click="open()" type="button" id="creategroup" class="btn ns-btn">
<img class="ns-add" src="images/createGroup.png">
<p class="create">Create Group</p>
</button>
<div>
<script type="text/ng-template" id="CreateGroupContent.html">
<div class="modal-header">
<h2 class="modal-title ns-modal-title">Create A Group</h2>
<button class="ns-modal-close" ng-click="cancel()"><img src="images/xCancel.png"></button>
</div>
<div class="modal-body">
<form class="form-signin" role="form">
<input type="text" class="form-control ns-modal-form" placeholder="Teacher" ng-model="create.teacher" required autofocus>
<input type="text" class="form-control ns-modal-form" placeholder="Group Name" ng-model="create.name" required>
</form>
</div>
<div class="modal-footer">
<button class="btn ns-modal-add ns-btn" ng-click="createGroupCall(create.teacher, create.name); ok();" type="submit">Create</button>
</div>
</div>
</script>
</div>
At first, you need to inject all in its order.
Also, you should inject $modal into the controller in which you would like to create your modal view. And the $modalInstance can be injected ONLY into the controller which is used for this $modal window. In your case you use the same controller, so you couldn't inject $modalInstance
Demo: http://plnkr.co/edit/khzNQ0?p=preview
Also, in your case (when you use only 1 controller) - you can pass as object field scope which will be used as parent of $scope for your modal view. By default it is $rootScope, but you can type:
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'CreateGroupContent.html',
controller: CreateGroupCtrl,
size: size,
scope: $scope
});
So now your functions ok() and cancel() will be available in your modal view and modal scope.
Looks like your FeedService and $modalInstance are mixed up. They need to be in the same order.