In my main html, I have a view which loads templates.
<div data-ng-view></div>
It loads a html whenever the link is clicked.
app.config(["$routeProvider", function ($routeProvider) {
'use strict';
$routeProvider
.when("/", {
templateUrl: "events.html"
});
}]);
On this page (template) , I have a directive which loads another html file
app.directive('ngPost', function () {
'use strict';
return {
restrict: 'A',
templateUrl: 'postbox.html'
};
});
I then use this directive on my events.html page by using <div data-ng-Post></div>
In postbox, I have two input fields and a button
<input type="text" id="user" data-ng-model="username" />
<input type="text" id="mess" data-ng-model="message"/>
<button data-ng-click="Add(eventid-1, username, message)">Post</button>
Upon clicking the button, I have some operations, then I try to clear the input fields, but I cannot. Method here :
$scope.Add = function (index, uname, msg) {
var a = {user: uname, message: msg, time: new Date()};
$scope.data[index].messages.push(a);
$scope.message = ''; // clearing here
$scope.username ='';
};
The clearing does not happen, I do not know why. My controller that has this Add method wraps the <div data-ng-view></div>in the main html file so it is the outermost controller and should have access to all $scope models inside. Why does it not work?
Note that the operations before the clearing works with no problems
Your add method is in the parent scope. The parent's scope cannot see it's children, it works the other way around. The message and username properties are defined in the directive's child scope. From a child you can reference parent properties, but not the other way around.
If you add scope: false and transclude: false to your directive, it won't create it's own scope and instead use its parent's scope, so your directive would look something like this:
angular.module('app', []).controller("myController",myController);
function myController($scope){
var ctrl = this;
ctrl.hello ="Hello"
};
angular.module('app').directive("childThing", function() {
return {
template: '<div>{{message}}</div><div>{{username}}</div>',
scope: false,
transclude: false,
controller: function($scope) {
$scope.username="Mike Feltman"
$scope.message="Hi Mike"
}
}
})
and you can access the elements that the directive adds to the scope from the parent like this:
<div ng-controller="myController as ctrl">
{{username}} in the parent.
<div>{{ctrl.hello}}</div>
<child-thing></child-thing>
</div>
Update using your template:
{{username}} in the parent.
{{ctrl.hello}}
Javascript:
function myController($scope){
var ctrl = this;
ctrl.hello ="Hello"
$scope.add = function() {
alert($scope.username)
}
};
angular.module('app').directive("childThing", function() {
return {
template: '<input type="text" id="user" data-ng-model="username" /><input type="text" id="mess" data-ng-model="message"/>',
scope: false,
transclude: false,
}
})
Related
Actually i was new to angular js i am trying to call my factory operation into controller i dont know where i am going wrong
and my js goes here
app.factory("myFactory",function(){
var something = {};
something.getsum = function() {
$scope.service = " heloo people"
}
return something;
});
app.controller("helloController", function($scope,myFactory) {
$scope.clickme = function() {
$scope.service=myFactory.getsum();
}
});
and my html goes here
<div ng-controller="hello controller">
<button ng-click="clickme"></button>
<h2>{{service}}</h2>
</div>
and my config goes here:
$urlRouterProvider.otherwise("/index/utilise");
$stateProvider
.state('index', {
abstract: true,
url: "/index",
templateUrl: "display.html",
controller:'mainController',
controllerAs: "parentCtrl",
})
.state('index.sample', {
url: "/home",
templateUrl: "content/sample.html",
})
.state('index.utilise', {
url: "/utilise",
templateUrl: "content/utilise.html",
})
})
First issue is that to use the myFactory factory in your controller you would need to inject it into the controller via dependency injection:
app.controller("helloController", function($scope, myFactory) {
$scope.clickme = function() {
$scope.service = myFactory.getsum();
}
});
Second issue you would not use $scope in the myFactory factory method getsum(), you would simply return the value you need:
app.factory("myFactory",function(){
var something = {};
something.getsum = function() {
return " heloo people";
}
return something;
});
Third issue is ng-click was not actually execute controller function clickme as there was parenthesis () as you would with any JavaScript function. It should be ng-click="clickme()" to actually call the function on the controller:
<div ng-controller="helloController">
<button ng-click="clickme()"></button>
<h2>{{service}}</h2>
</div>
Finally, it's unclear what the structure of your application based on the ui-router configuration your provided. With ui-router you wouldn't really have the need to use ng-controller as you can specify what controller any given view should be using. I've created multiple Plunkers, one and two, demonstrating the factory functionality with and without controllers specified for child routes. This should be more than enough to demonstrating calling a controller function in different situations.
Hopefully that helps!
I'm in the middle of refactoring an old project to use custom directives, and I'm already running into a problem. I'm just trying to make a simple directive and build from there. I have a logger function in my directive's link function that just runs a console.log. I'm not sure what I'm missing here, and I'm sure it's something simple. Here's my directive:
'use strict';
(function() {
angular
.module('sigFig')
.directive('myDirective', myDirective);
function myDirective(sigFigFactory) {
var directive = {
restrict: 'E',
replace: 'true',
templateUrl: 'Directives/directiveTemplate.html',
link: link,
compile: compile
};
return directive;
function link(scope, element, attrs) {
scope.logger = function() {
console.log('DING!!!');
}
}
function compile(scope, element, attrs) {
console.log('I AM A COMPILE FUNCTION');
}
}
})();
The HTML template for it is just:
<button ng-click="logger()">CLICK ME</button>
And I'm calling it in my HTML like this:
<my-directive></my-directive>
The button appears and that console.log in my compile works, but the ng-click does not. What is it I'm missing? Thanks in advance!
Add scope to directive variable: scope:{},
function myDirective(sigFigFactory) {
var directive = {
scope:{},
restrict: 'E',
replace: 'true',
templateUrl: 'Directives/directiveTemplate.html',
link: link,
compile: compile
};
return directive;
I have never created an angular application without a controller. So I'm positive that that is your issue here.
Example of your code with a controller.
html:
<body ng-app='sigFig' ng-controller='ctrl'>
<my-directive></my-directive>
</body>
js:
(function() {
angular.module('sigFig', [])
.controller('ctrl', function($scope){
$scope.itemH = 'hahaha'
})
.directive('myDirective', myDirective);
function myDirective() {
return {
restrict: 'E',
template: '<button ng-click="logger()">{{item}}</button>',
link: function link(scope, element, attrs) {
scope.item = "Logger Click Me";
scope.logger = function() {
alert('logger')
}
}
};
function compile(scope, element, attrs) {
console.log('I AM A COMPILE FUNCTION');
}
}
})();
I have a view with a ui.bootstrap modal that has its own controller.
In the view, i have a directive that generates a number of buttons with a unique ID.
I want to be able to click on one of the buttons generated and call the main view's controller to launch the modal.
Here is the main view module:
/* global angular */
angular.module('my.jobs', [
'ui.router',
'ui.bootstrap'
])
.controller('DashboardJobsCtrl', function DashboardJobsController($rootScope, $scope, $log, $state, $modal) {
var self = this;
angular.extend(this, {
displayReceipt: function(jobId) {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'receiptModal.html',
size: 'lg',
controller: function($scope, $modalInstance, jobsService) {
//CODE HERE FOR ADDING VALUES TO THE MODAL...
$scope.clear = function() {
$modalInstance.close();
};
}
});
}
});
});
Here is the directive:
angular.module('jobView', ['ui.router', 'ui.bootstrap'])
.directive('jobView', function($compile, $http, $templateCache, DOMAINS) {
return {
restrict: 'E',
scope: {
job: '=',
view: '#'
},
template: 'myTemplate.html',
link: function($scope, element, attrs) {
//ASSUME THERE IS CODE HERE FOR GENERATING UNIQUE ID FOR JOBS
//NEXT LINE I WANT TO CALL MODAL FROM THE MAIN VIEW MODULE
$scope.displayReceipt('jobId')
}
};
});
I know this is a simple scope issue, but it's driving me nuts that I can't make the connection.
Here is the perfect example. calling method of parent controller from a directive in AngularJS.
I have update your example below.
<job-View updateParent='displayReceipt()'></job-View>
angular.module('jobView', ['ui.router', 'ui.bootstrap'])
.directive('jobView', function($compile, $http, $templateCache, DOMAINS) {
return {
restrict: 'E',
scope: {
job: '=',
view: '#',
updateParent:'&'
},
template: 'myTemplate.html',
link: function($scope, element, attrs) {
//ASSUME THERE IS CODE HERE FOR GENERATING UNIQUE ID FOR JOBS
//NEXT LINE I WANT TO CALL MODAL FROM THE MAIN VIEW MODULE
$scope.displayReceipt('jobId')
}
};
});
Below is the template I am using for the directive. In code we are
fetching the data from a service in that data we have all the
information of that particular person. And from that data we are
showing only first name, last name and designtion or company
affiliation.
<div ng-if="model" class="entry-added">
<span class="form-control"><b>{{model.fullName}}</b>, <br/><span class="small-font">{{(model.designation)?model.designation:model.companyAffiliation}}</span></span>
<a ng-click="removePerson()" class="action-remove"><i class="fa fa-remove"></i></a>
</div>
<div ng-show="!model" class="input-group">
<input type="text"
class="form-control"
name="{{name}}"
id="{{name}}"
placeholder="{{placeholder}}"
ng-required="{{isRequired}}"
typeahead-on-select = "change($item, $model, $label)"
ng-model="model"
typeahead-min-length="3",
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
typeahead-template-url="typeAheadTemplate.html"
typeahead-loading="searching"
typeahead-editable="false">
<script type="text/ng-template" id="typeAheadTemplate.html">
<a class="ui-corner-all dropdown" tabindex="-1">
<div class="col-md-2"><img class="dropdown-image" ng-src="https://people.***.com/Photos?empno={{match.model.employeeNumber}}"></div>
<div>
<div bind-html-unsafe="match.model.fullName"></div>
<div bind-html-unsafe="match.model.designation"></div>
</div>
</a>
</script>
I am using a custom directive to display a search field. The drop down is displaying [object object].
Directive
// In backend taxDeptContact is a Person type object
/*
Directive code
*/
(function () {
'use strict';
angular.module('treasuryApp.directives').directive('employeeSearch', employeeSearch);
employeeSearch.$inject = ['$resource', '$rootScope', 'ErrorHandler'];
function employeeSearch($resource, $rootScope, ErrorHandler) {
return {
restrict: 'E',
require: '^form',
scope: {
model: "=",
isRequired: '#',
submitted: "=",
onSelect: '&',
name: '#',
index:'#'
},
link: function(scope, el, attrs, formCtrl) {
//set required attribute for dynamically changing validations
scope.searchEmployees = function (searchTerm) {
var users = [];
var myResult = [];
var result = $resource($rootScope.REST_URL + "/user/getEmployees", {term: searchTerm}).query().$promise.then(function (value) {
//console.log(value)
$.each(value, function(i, o) {
users.push(o);
});
return users;
});
return result;
}
scope.removePerson = function() {
scope.model=null;
}
scope.userNotSelectedFromTypeahead = function(name) {
if(undefined === formCtrl[name]) {
return false;
}
return formCtrl[name].$error.editable;
};
scope.change = function(item, model, label) {
scope.model = item
scope.onSelect(
{name: scope.name, person: scope.model});
},
templateUrl: 'app/components/common/directives/employee-search.tpl.html'
};
}
})();
View that is using the directive
<div class="form-group">
<label class="col-sm-3>Tax Dept Contact</label>
<div class="col-sm-4">
<employee-search model="reqCtrl.requestObj.taxDepartmentContact" name="taxDeptContact" is-required="false" submitted="reqCtrl.submitted"/>
</div>
</div>
Image of the error occuring
Looks like this may be your trouble spot
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
suggestion for suggestion is pulling the whole object. Have you tried displaying a particular attribute of suggestion?
For example: if you had a suggestion.name attribute you would write:
typeahead="suggestion.name for suggestion in searchEmployees($viewValue)"
Finally got the answer: I used autocomplete="off" in my directive and thats all
<input type="text" autocomplete="off" />
I have a Angular SPA in which things are working fine except that the business wants me to move the code from this link-group.html (which has its own controller, module etc..)
The URL with the code to put into a template or place the code underneath the other html code supervisors.html
URL for News that is in link-group.html that I need to move:
http://localhost:1337/doc-home/#/tips/2?paginatePage=1
File:
link-group.html
Location:
Then the location of where I needs to display (move to)
URL:
http://localhost:1337/doc-home/#/supervisors
File:
supervisors.html
Location:
Template? controller reference?
UPDATE
I want to take all the code from the link.group.html and move it to the supervisor.html page
However, there is specific code that is referring to the controller/module/database that is based on the URL
<div class="links-group" ng-repeat="group in groups" ng-show="!group.hidden">
<div ng-show="!edit" style="margin: 5px 0;">
<h3>{{ group.title }}</h3>
<div ng-show="edit === true">
<input style="margin: 5px 0" placeholder="title..." class="input" ng-model="group.title" />
UPDATE 2 per suggestion from OP
Current controller.js for supervisor.html
angular.module('supervisors')
.controller('SupervisorsCtrl',
function ($scope, UserService) {
UserService.get(function (err, user) {
$scope.user = user;
});
});
So in order to modify can I add another module underneath it?
angular.module('supervisors')
.controller('SupervisorsCtrl',
function ($scope, UserService) {
UserService.get(function (err, user) {
$scope.user = user;
});
});
angular.module('linkgroup', ['ng'])
.directive('linkgroup', function({{ dependencies of your controller here }}) {
return {
templateUrl: {{ url of the template, likely link-group.html }},
link: function($scope, $element, $attributes) {
// think of this as the controller of a directive
{{ code of your controller,
replace `this` with `$scope` if you used ControllerAs }}
}
};
});
Seems that there is NO module.js in the common folder, there is a directives.js and controller.js
However I see that with links folder there is this code
angular.module('links')
.controller('LinksCtrl', function ($scope, LinksService, SearchService, UserService, notify, $window, $location) {
$scope.message = "";
UserService.get(function (err, user) {
if (err) {
notify.error('Error getting current user.');
} else {
if (user.groups.WEB_ESO !== true) {
$location.path('/');
}
}
});
Sounds like you could get away with a directive that contains your link-group. Transformation is pretty straightforward (if you used $scope in your controller it's almost direct copy+paste):
angular.module('linkgroup', ['ng'])
.directive('linkgroup', function({{ dependencies of your controller here }}) {
return {
templateUrl: {{ url of the template, likely link-group.html }},
link: function($scope, $element, $attributes) {
// think of this as the controller of a directive
{{ code of your controller,
replace `this` with `$scope` if you used ControllerAs }}
}
};
});
Then in supervisors.html add <linkgroup></linkgroup> at the bottom.