How to call link function method from html ng-click? - javascript

I have the following code in my directive:
testModule.directive('TestOne',function(){
return{
replace: true,
controller: 'TestCtrl',
link: function(scope, element, attrs){
element.on('click', function(e) {
//my own code is there
});
}
}
}
I wanted to call the above click function on ng-click with the below event in html(ng-click="mytest()"). How can I call or write exactly so that I can execute my function requirements in the above directive's element click function as per my requirements.
html:
<div test-one ng-repeat="items in testjson">
<div class="title">{{items.name}}</div>
<div class="context-menu">
<ul>
<li ng-click="mytest()">TestFunction</li>
</ul>
</div>
</div>
Thanks in advance.

First make the first letter of the directive simple
directive('TestOne',function(){
to
directive('testOne',function(){
Then create a scope function for ng-click inside the link function
.directive('testOne',function(){
return{
restrict : 'A',
replace: true,
link: function(scope, element, attrs){
scope.mytest = function() {
console.log("working")
}
}
}
})
Demo
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.testjson = [{"name":"sss"},{"name":"ssss"}]
}).directive('testOne',function(){
return{
restrict : 'A',
replace: true,
link: function(scope, element, attrs){
scope.mytest = function() {
console.log("working")
}
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div test-one ng-repeat="items in testjson">
<div class="title">{{items.name}}</div>
<div class="context-menu">
<ul>
<li ng-click="mytest()">TestFunction</li>
</ul>
</div>
</div>
</div>

Related

Using directives in angular

I am quite new to angular.
I am trying to manage a list of contacts to be able to select one to display some details on the side. I was able to do it without directives but then I wanted to use directives and be able to show which one is selected in the list.
With directives I am able to display the list but when I select a contact it doesn't show details anymore so the select is not working and I can't get it to work as those directives are making me crazy.
Here is contact.html:
<li><a href selected="selected" ng-click='selectContact(contact)' ng-transclude></a></li>
// Code goes here
var app = angular.module("contactList", []);
app.service("peopleService", function($http) {
this.getPeople = function() {
return $http.get('people.json');
};
});
app.controller("peopleController", function($scope, peopleService) {
$scope.selectedContact = {};
$scope.selectedContactImage = ""
$scope.showDetail = false;
peopleService.getPeople().then(function(response) {
$scope.people = response.data.People;
});
$scope.selectContact = function(contact) {
$scope.selectedContact = contact;
if (contact.img) {
$scope.selectedContactImage = contact.img;
}
$scope.showDetail = true;
};
});
app.directive("contactList", function(){
return{
restrict: 'EA',
replace: true,
transclude: true,
template: "<div ng-transclude></div>",
controller: function(){
this.gotOpened = function(selectedContact){
contacts.forEach(function(contact){
if(selectedContact != contact){
contact.selected = false;
}
});
};
}
};
});
app.directive("contact", function(){
return {
restrict: 'EA',
replace: true,
transclude: true,
require: '^?contactList',
scope: {selected: '='},
templateUrl: 'contact.html',
link: function(scope, element, attrs, contactListController){
scope.selected = false;
scope.selectContact = function selectContact(){
scope.selected = !scope.selected;
contactListController.gotOpened(scope);
};
}
};
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script data-require="angularjs#1.6.4" data-semver="1.6.4" src="https://code.angularjs.org/1.6.4/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="contactList">
<div ng-controller="peopleController">
<contact-list>
<contact class="contact" ng-repeat="contact in people">
{{contact.name}}
</contact>
</contact-list>
<div class="list">
<ul>
<li ng-repeat="p in people">
<a href ng-click='selectContact(p)'>{{p.name}}</a>
</li>
</ul>
</div>
<div class="detail" ng-show="showDetail">
<div class="detailimagewrapper">
<img class="detailimage" src="{{selectedContactImage}}">
</div>
<label>Rating</label>
<p>{{selectedContact.rating}}</p>
<label>Description</label>
<p>{{selectedContact.Description}}</p>
</div>
</div>
</body>
</html>
Looks like you are using transclude and replace here. I expect this is causing your anchor tag to be replaced by the content which your contact directive is wrapping. Try removing the ng-transclude attribute from the anchor tag and instead adding <ng-transclude></ng-transclude> within the anchor tag.
contact.html would become:
<li>
<a href selected="selected" ng-click='selectContact(contact)'>
<ng-transclude></ng-transclude>
</a>
</li>

ng-click not working within directive

This is the directive with the function that is supposed to be called when clicked.
ebApp.directive('monthDir', function () {
return {
restrict: 'E',
templateUrl: 'htmlFiles/monthDirective.html',
transclude: true,
scope: {
ebObj: "=obj"
},
link: function link(scope, element, attrs, ngModelCtrl) {
scope.removeDir = function (removeVal) {
console.log("asd"); //not showing in the console
}
console.log(scope);
},
controller: function ($scope) {
}
}
})
The ng-click in the following directive is not working. The directive's html
<div class="row monthDirC">
<span class="glyphicon glyphicon-remove-sign pull-right cursorC"
ng-click="removeDir(ebObj.costArray[count])" ></span>
<div class="form-group">
<label for="datepick" class="col-md-6">Select month</label>
<md-datepicker id="datepick" class="col-md-6" ng-model="ebObj.costArray[count].myDate"
md-placeholder="Enter date"
md-min-date="minDate"
md-max-date="maxDate">
</md-datepicker>
</div>
The html that uses the directive:
<div class="col-md-12">
<month-dir ng-transclude ng-repeat="count in ebObj.costArray[0].countArray" obj="ebObj.costArray[count+1]"></month-dir>
</div>
It is working correctly. Make sure you don't have any errors. Try this,
var ebApp = angular.module('ebApp', []);
ebApp.controller('MainCtrl', function($scope) {
$scope.ebObj = 'someVal';
});
ebApp.directive('monthDir', function() {
return {
restrict: 'E',
template: '<div ng-click="removeDir()"><b>Click Me</b><ng-transclude></ng-transclude></div>',
transclude: true,
scope: {
ebObj: '=obj'
},
link: function link(scope, element, attrs, ngModelCtrl) {
scope.removeDir = function (removeVal) {
console.log('asd'); //not showing in the console
}
},
controller: function ($scope) {
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="ebApp" ng-controller="MainCtrl">
<month-dir ebObj="ebObj"><i>Click Me!</i></month-dir>
</div>

angular: calling/triigering directive method from parent scope

in my app I defined a directive which implement a simple slider with a next/prev/goto methods.
The slider then is within an html snipet managed by another controller.
The problem is that the last slide contains a form, so if the submit is ok than I would like to go to the next slide.
In old javascript I would have passed a callback to the submit method in order to apply that callback.
I made the same thing. Is this the best / angular style way to do it?
Javascript (I omitted some detail):
.directive("sfCarousel", function() {
return {
scope: true,
restrict: 'A',
controller: function($scope) {
var slides = $scope.slides = [];
var currentIndex = $scope.currentIndex = -1;
$scope.next = function() {
//mynextfunction...
}
},
link: function(scope, element, attrs) {
console.log("sf-carousel");
}
}
})
.directive("sfCarouselItem", function() {
return {
scope: true,
require: '^sfCarousel',
link: function(scope, element, attrs, sfCarouselController) {
console.log("sf-carousel-item");
sfCarouselController.addSlide(scope);
}
}
})
.controller("mycontroller", ['$scope', function($scope) {
$scope.submit = function (callback) {
//if submit is ok then
callback.apply(null, []);
}
}])
HTML:
<div sf-carousel >
<div sf-carousel-item ng-class="{'active':active}" >
<div>my first slide</div>
<div sf-label="get-started.submit" ng-click="next()" ></div>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<form>
<!--here my form-->
<button type="submit" ng-click="submit(next)">submit and go</button>
</form>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<div>my last slide</div>
<!--other things-->
</div>
</div>
You can pass the function that you what to run on the parent controller.
// directive sfCarousel
return {
transclude: true,
template: '<div class="sf-carousel" ng-transclude></div>',
// ...
};
// directive sfCarouselItem
return {
transclude: true,
scope: {
func: '&',
// ...
},
template: '<div class="sf-carousel-item" ng-transclude></div>',
}
// controller html
<div sf-carousel >
<div sf-carousel-item ng-class="{'active':active}" >
<div>my first slide</div>
<div sf-label="get-started.submit" ng-click="next()" ></div>
</div>
<div sf-carousel-item func="next()" ng-class="{'active':active}" >
<form>
<!--here my form-->
<button type="submit" ng-click="func({})">submit and go</button>
</form>
</div>
<div sf-carousel-item ng-class="{'active':active}" >
<div>my last slide</div>
<!--other things-->
</div>
</div>

angularjs template binding

I have developed a transclude directive and I set it to use angularjs template script everything works fine but I still cannot access the bind data.
My code:
index.html
<div side-element="box" title="Links">
<ul>
<li>Link 1</li>
<li>Link 2</li>
</ul>
</div>
<script id="box" type="text/ng-template">
<div class="side-box">
<div class="content">
<h2 class="header">Box {{ title }}</h2>
<span class="content" ng-transclude></span>
</div>
</div>
</script>
<script id="ad" type="text/ng-template">
<div class="side-ad">
<div class="content">
<h2 class="header">AD {{ title }}</h2>
<span class="content" ng-transclude></span>
</div>
</div>
</script>
app.js:
angular.module('myApp.directives')
.directive('sideElement', function ($templateCache, $log) {
return {
scope: {
title: '#'
},
transclude: 'element',
link: function(scope, element, attrs, ctrl, transclude){
var template = $templateCache.get(attrs.sideElement);
var templateElement = angular.element(template);
$log.info(scope.title);//Output the title i put in the html which is (Links)
transclude(scope, function(clone){
element.after(templateElement.append(clone));
});
}
};
});
the scope inside the link function(....) displaies the correct title but it doesn't work in the html:
Box {{ title }}
Link 1
Link 2
I think I missed one thing but I can't figure it out, I need your help to complete the cycle.
Thanx in advance,
The template element that contains the angular binding expressions must be compiled first, and then linked. The compilation phase prepares the template, while the linking phase sets up your $watchers for your binding expressions.
Demo Here
Here is a compile function that should work:
.directive('sideElement', function ($templateCache, $compile, $log) {
return {
restrict: 'A',
transclude: true,
scope:'#',
compile: function(element, attrs) {
var template = $templateCache.get(attrs.sideElement);
var templateElement = angular.element(template);
element.append(templateElement);
return function(scope, element, attr, ctrl, transclude) {
$log.info(scope.title);
}
}
}

Create a list of items built using angularjs

I would like to create a list of items built in Directive and share through controllers.
Here is my example in plunker: Example of my code
Here is my code in js:
var app = angular.module('app', []);
app.controller("BrunchesCtrl", function ($scope, $log) {
$scope.brunches = [];
$scope.addNew = function () {
$scope.brunches.push({ address: "" });
};
$scope.$watch('brunch.address', function(value) {
$scope.address = value;
$log.info($scope.address);
});
$scope.$watch(function() { return $scope.brunches.length; }, function() {
$scope.brunches = $scope.brunches.map(function (brunch) {
return brunch;
});
});
});
app.directive('brunchesView', function ($compile) {
return {
restrict: 'E',
templateUrl: 'brunch.html',
controller: 'BrunchesCtrl',
replace: true,
link: function (scope, element, attrs, controller) {
}
};
});
app.directive('businessSubmit', function ($log, $compile, formManagerService) {
return {
restrict: 'AE',
controller: 'BrunchesCtrl',
link: function (scope, element, attrs, controller) {
formManagerService.init();
var hasError;
element.on('click', function (e) {
e.preventDefault();
$log.info("brunches: \n");
$log.info(scope.brunches);
});
}
};
});
Here is an HTML:
<!DOCTYPE html>
<div class="controls">
<a class="btn btn-danger" id="addBrunch" data-ng-click="addNew()">
<i class="icon-plus-sign"></i>
add new...
</a>
</div>
</div>
<brunches-view class="well" data-ng-repeat="brunch in brunches">{{brunch}}</brunches-view>
<br/>
<p class="well">
JSON: {{brunches | json}}
</p>
<div class="control-group">
<div class="controls">
<a class="btn btn-primary" href="#" data-business-submit>
<i class="icon-save"></i>
Save...
</a>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="script.js"></script>
And here is the template:
<div class="fc-border-separate">
<div class="control-group">
<label class="control-label">Address</label>
<div class="controls">
<input type="text" class="span6 m-wrap"
name="Address" data-ng-model="address"
value="{{address}}" />
</div>
</div>
</div>
The final thing I want to save the whole data inside the BusinessSubmit directive.
Help please...
Several issues with your code.
First, your ng-model for the <input> is set to address, but the object you are wanting to bind it to a brunch object that has an address property. Important to realize that ng-repeat will create a child scope for every repeated item
<input data-ng-model="brunch.address"/>
Another issue is you are assigning the parent controller to a directive as well. Important to understand that controllers are singletons so if you use controller more than once , each is a separate instance. Therefore nesting the parent controller in a directive makes no sense.
DEMO- [ng-model] fix
If you want the data shared with other controllers you should set up a service that holds the brunches data by injecting it into whatever controllers will need access

Categories