Send an event using $emit from directive to controller - javascript

I'm trying to send an event when an item gets selected, from directive to controller using $emit. I've two update functions for organizations and another for people. My directive should specify which event should emit.
Here is my update functions:
// For organization
$scope.updateOrgs = function(selectedVal) {
}
// For people
$scope.updatepeople = function(selectedVal, type) {
}
When it is people my directive should raise an emit event for updatepeople (), if it was org it should raise updateorg().
My directive looks like:
.directive('search', function ($timeout) {
return {
restrict: 'AEC',
scope: {
model: '=',
searchobj: '#',
},
link: function (scope, elem, attrs, index) {
scope.handleSelection = function (selectedItem) {
scope.model = selectedItem;
scope.searchModel="";
scope.current = 0;
scope.selected = true;
$timeout(function () {
scope.onSelectupdate();
}, 200);
};
scope.Delete = function (index) {
scope.selectedIndex = index;
scope.delete({ index: index });
};
scope.Search = function (searchitem,event,searchobj) {
// alert('item entered'+name)
scope.searching = searchitem;
scope.searchobject = searchobj;
scope.onSearch({ searchitem: searchitem , searchobj:searchobj});
};
scope.current = 0;
scope.selected = true;
scope.isCurrent = function (index) {
return scope.current == index;
};
scope.setCurrent = function (index) {
scope.current = index;
};
},
controller: ['$scope','$element','$rootScope','SearchOrg', function($scope,$element,$rootScope,SearchOrg) {
$scope.searchItem = function(filter,searchobj){
//alert('search'+searchobj);
SearchOrg().fetch({'filter': filter, 'searchType': searchobj}).$promise.then(function(value){
$scope.searchData = value.data;
console.info($scope.searchData);
},
function(err) {
});
}
}],
templateUrl: TAPPLENT_CONFIG.HTML_ENDPOINT[0] + 'home/genericsearch.html'
}
});;
HTML snippet
<search searchobj=“tei-org” selectedItems=“arrayofIds” search-id=”someidtoIdentify”/>
How can I do this both functions are in different controllers, and also I need to send parameters from directive to the controller using $emit?

Working with $scope.$emit and $scope.$on
I'm guessing that your other controllers are not parents, so look at the second option using $broadcast.
var app = angular.module('app', []);
app.controller('firstController', function($scope) {
$scope.selectedOrgs = []
$scope.$on('updateorgs', function(evt, data) {
$scope.selectedOrgs.push(data);
});
});
app.controller('secondController', function($scope) {
$scope.selectedPeople = []
$scope.$on('updatepeople', function(evt, data) {
$scope.selectedPeople.push(data);
});
});
app.directive('someDirective', function($rootScope) {
return {
scope: {},
link: function(scope) {
scope.options = [{
id: 1,
label: 'org a',
type: 'org'
}, {
id: 2,
label: 'org b',
type: 'org'
}, {
id: 3,
label: 'person a',
type: 'person'
}, {
id: 4,
label: 'person b',
type: 'person'
}];
scope.changed = function() {
if (scope.selected) {
var updatetype = scope.selected.type;
if (updatetype === 'person') {
$rootScope.$broadcast('updatepeople', scope.selected);
} else if (updatetype === 'org') {
$rootScope.$broadcast('updateorgs', scope.selected);
}
}
};
},
template: '<select ng-change="changed()" ng-model="selected" ng-options="option.label for option in options"><option value="">Select</option></select>'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app='app'>
<some-directive></some-directive>
<div ng-controller='firstController'>
<div>ORGS:</div>
<div>
{{ selectedOrgs }}
</div>
</div>
<div ng-controller='secondController'>
<div>PEOPLE:</div>
<div>
{{ selectedPeople }}
</div>
</div>
</div>

Related

How to make my button (clear filters) only appears when filters are use

well that's really my question. I have a button that clears all my filters but I only want it to be shown when any of the filters is used. How can I make that? I need that appears when range filter or filter hotel is used. thanks!!
Button that clear filters
.filterheader
.filter-ctn
.filterheader
h4 Filtrar
span(class="delete-filter" ng-click="$ctrl.hotelsResultController.$onInit()")<i class="fa fa-times" aria-hidden="true"></i> Eliminar Filtros
.filtercontainer
hotel-root-component.js
(function () {
'use strict';
angular
.module('hotelsResult')
.component('hotelsRoot', {
bindings: {},
controller: hotelsResultController,
templateUrl: "hotel-result/hotels-root.html"
});
hotelsResultController.$inject = ['hotelsService'];
function hotelsResultController(hotelsService) {
const self = this;
self.filterOnHotels = [];
this.$onInit = function () {
hotelsService.getHotels().then(function (hotels) {
self.hotels = hotels;
self.filterOnHotels = hotels;
});
this.filters = {
"name" : "",
"targetName" : "",
"price":{
"priceMin" : 0,
"priceMax": 3250,
},
"stars":{
"all": true,
"five": false,
"four": false,
"three" : false,
"two" : false,
"one" : false
},
}
};
this.getHotels = function () {
return self.filterOnHotels;
};
}
})();
filter-header.component.js
(
function (){
'use strict';
angular
.module('filters')
.component('filterHeader', {
bindings:{},
require: {
hotelsResultController : '^hotelsRoot'
},
controller: filterHeaderController,
templateUrl: "hotel-result/filters/filterheader/filterheader.html"
});
function filterHeaderController() {}
})();
filter-hotel.component.js
(function (){
'use strict';
angular
.module('filters')
.component('filterHotel', {
bindings:{
"filters" : '<'
},
templateUrl: 'hotel-result/filters/filterhotel/filterhotel.html'
}).filter('filterHotel', function() {
var self = this;
return function (hotels,targetName) {
return hotels.filter(function (hotel) {
return hotel.name.toLowerCase().indexOf(targetName.toLowerCase()) != -1;
})
}
})
})();
filter-range.component.js
(function (){
'use strict';
angular
.module('filters')
.component('filterNight',{
controller: filterNightController,
require: {
hotelsResultController : '^hotelsRoot'
},
bindings:{
"filters" : '<'
},
templateUrl: "hotel-result/filters/filternight/filternight.html"
}).filter('filterNight',function () {
return function (hotels,price) {
return hotels.filter(function (hotel) {
return (hotel.price >= price.priceMin && hotel.price <= price.priceMax);
});
}
});
function filterNightController (){
let self = this;
this.slider = {
value: 150,
options: {
minRange: 200,
noSwitching: true,
pushRange: true,
onChange : this.filterNight
}
};
}
})();
item-list.jade
ul
li(ng-repeat="hotel in $ctrl.hotels | filterHotel: $ctrl.filters.targetName | filterStar: $ctrl.filters.stars | filterNight: $ctrl.filters.price")
item(item='hotel')
you can keep the filterd result by the following:
ul
li(ng-repeat="hotel in filterResult = ($ctrl.hotels | filterHotel: $ctrl.filters.targetName | filterStar: $ctrl.filters.stars | filterNight: $ctrl.filters.price)")
item(item='hotel')
and compare the result with the original data, if the filters are being used then they will be different from each other.
span(class="delete-filter" ng-if="filterResult.length !== $ctrl.hotels.length" ng-click="$ctrl.hotelsResultController.$onInit()")<i class="fa fa-times" aria-hidden="true"></i> Eliminar Filtros
refer example below:
angular.module("app", [])
.controller("myCtrl", function($scope) {
$scope.data = [
{
id: 1,
data: 'data for item1'
},
{
id: 2,
data: 'data for item2'
},
{
id: 3,
data: 'data for item3'
},
{
id: 4,
data: 'data for item4'
}
];
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<input type="text" ng-model="test">
<button ng-if="filterResult.length !== data.length">Filter Used</button>
<div ng-repeat="item in filterResult = (data | filter: test)">
<span>{{item.id}} - {{item.data}}</span>
</div>
</div>

Angular - getting value from directive in the controller

I need to pass a selected value from a directive that I am using in several places. It is a select input field that I need to get a selected value from.
This is how the directive looks like:
angular.module('quiz.directives')
.directive('fancySelect', function($rootScope, $timeout) {
return {
restrict: 'E',
templateUrl: 'templates/directives/fancySelect.html',
scope: {
title: '#',
model: '=',
options: '=',
multiple: '=',
enable: '=',
onChange: '&',
class: '#'
},
link: function(scope) {
scope.showOptions = false;
scope.displayValues = [];
scope.$watch('enable', function(enable) {
if (!enable && scope.showOptions) {
scope.toggleShowOptions(false);
}
});
scope.toggleShowOptions = function(show) {
if (!scope.enable) {
return;
}
if (show === undefined) {
show = !scope.showOptions;
}
if (show) {
$rootScope.$broadcast('fancySelect:hideAll');
}
$timeout(function() {
scope.showOptions = show;
});
};
scope.toggleValue = function(value) {
if (!value) {
return;
}
if (!scope.multiple) {
scope.model = value;
console.log(scope.model);
return;
}
var index = scope.model.indexOf(value);
if (index >= 0) {
scope.model.splice(index, 1);
}
else {
scope.model.push(value);
}
if (scope.onChange) {
scope.onChange();
}
};
scope.getDisplayValues = function() {
if (!scope.options || !scope.model) {
return [];
}
if (!scope.multiple && scope.model) {
return scope.options.filter(function(opt) {
return opt.id == scope.model;
});
}
return scope.options.filter(function(opt) {
return scope.model.indexOf(opt.id) >= 0;
});
};
$rootScope.$on('fancySelect:hideAll', function() {
scope.showOptions = false;
});
}
};
});
When I do console.log(scope.model); I get the selected value, but I am not sure how to get it and use it in my controller?
This is the controller:
angular.module('quiz.controllers')
.controller('ProfileController', function(
$scope,
$state,
$stateParams,
UserService,
$auth,
MessageService,
$ionicLoading,
AppSettings,
$timeout,
AvatarService,
PushService,
$http
) {
$scope.user = UserService.get();
$scope.profilePromise = {};
if ($scope.user.player.avatar == ""){
$scope.user.player.avatar = AvatarService.getRandom();
}
$http.get(AppSettings.apiUrl + '/years')
.then(function(result) {
$scope.years = result.data;
});
$scope.updateUser = function(form) {
if (!form.$valid) {
var message = "Ugyldig data i skjema. Sjekk felter markert med rødt.";
MessageService.alertMessage(message);
return;
}
saveUser($scope.user);
};
$scope.getNextAvatar = function() {
$scope.user.player.avatar = AvatarService.getNext($scope.user.player.avatar);
};
$scope.getPreviousAvatar = function() {
$scope.user.player.avatar = AvatarService.getPrevious($scope.user.player.avatar);
};
var saveUser = function(user) {
$scope.profilePromise = UserService.save(user);
$scope.profilePromise.then(function(result) {
$scope.user = result.data.user;
PushService.init();
PushService.getDeviceId().then(function(id) {
UserService.addDevice(id);
});
if ($stateParams.register) {
$state.go('main.front');
}
}, function(error) {
var message = "Kunne ikke lagre bruker. Melding fra server: " + error.data.message;
MessageService.alertMessage(message);
});
};
});
You already have an onChange binding in the scope, so why don't you use that one?
In your directive:
if (scope.onChange) {
scope.onChange({ $value: scope.model });
}
Then pass a controller function to your directive:
<fancy-select on-change="onChange($value)"></fancy-select>
In your controller:
$scope.onChange = function(val) {
// do something with the value
}

why ng-click not working?

I write a directive to impl ng-disabled because i just can use angularjs which version is 1.1.5,it't not provide ng-disabled,so
tableApp.directive('myDisabled', function($compile) {
return {
restrict: 'A',
replace: true,
scope: {
myDisabled: '='
},
link: function(scope, element, attrs) {
var test = scope.$eval(attrs.myDisabled);
console.log(test);
scope.$watch(attrs.myDisabled, function (test) {
if (test) {
element.attr();
}
else {
element.attr('disabled', 'false');
}
});
}
};
});
the html code:
<html ng-app="tableApp">
<head></head>
<body>
<div ng-controller="TableCtrl">
<input ng-model="page"/>
<button class="btn btn-primary" ng-click="previouspage()" my-disabled="page <=1">上一页</button>
</div>
</body>
</html>
but why i click this button,it can't call the function previouspage()
this is my angularjs code
var tableApp = angular.module('tableApp', [], function ($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded;charset=utf-8';
});
tableApp.directive('myDisabled', function($compile) {
return {
restrict: 'A',
replace: true,
scope: {
myDisabled: '='
},
link: function(scope, element, attrs) {
var test = scope.$eval(attrs.myDisabled);
console.log(test);
scope.$watch(attrs.myDisabled, function (test) {
if (test) {
element.attr();
}
else {
element.attr('disabled', 'false');
}
});
$compile(attrs);
}
};
});
tableApp.controller('TableCtrl', function ($scope, $http) {
$scope.page = 1;
$scope.getCr = function getCr(later) {
var url = '/cms/copyright/find';
var request = $http({
method: 'get',
url: url,
params: {
page_length: 25,
start: ($scope.page - 1) * 25,
s: ''
}
});
request.then(function (data) {
if (data.data.result == 'OK') {
console.log(data.data);
$scope.copyright = data.data;
if (later != undefined) {
later();
}
}
});
};
$scope.nextpage = function nextpage() {
$scope.page += 1;
$scope.getCr();
};
$scope.onepage = function onepage() {
$scope.page = 1;
$scope.getCr();
};
$scope.previouspage = function previouspage() {
$scope.page -= 1;
$scope.getCr();
};
$scope.setPos = function setPos(index, holder_id) {
var pos = window.prompt("请输入排序位置", $scope.copyright.items[index].pos);
console.log(pos);
if (pos != null && pos != "" && parseInt(pos) > 0) {
var a = 'holder_id=' + holder_id + '&pos=' + pos;
$http.post('/cms/copyright/top', a).then(function (data) {
data = data.data;
if (data.result == 'OK') {
$scope.getCr(function () {
$scope.copyright.items[index].change = true;
});
} else {
alert(data.result);
}
});
}
console.log($scope.copyright.items[index]);
};
$scope.getCr();
});
Your problem is related to $scope.
When you are explicitly creating an isolated scope in your directive (using scope: {}) you can't access parent scope directly. If you don't, there is no problem doing so.
So, in short, just change ng-click="previouspage()" to ng-click="$parent.previouspage()" inside your HTML template.
Related plunker here: http://plnkr.co/edit/WRflPF
You could also refactor your directive's link function and remove unnecessary properties. So directive could be:
app.directive('myDisabled', function () {
return {
restrict: 'A',
scope: {
myDisabled: '='
},
link: function(scope, element) {
scope.$watch('myDisabled', function (val) {
element.attr('disabled', val);
});
}
};
});
The problem is the directive scope. You try to access an scope variable from parent scope (your controllers scope)
If you disable the isolate scope for your directive it works
For example:
tableApp.directive('myDisabled', function($compile) {
return {
restrict: 'A',
replace: true,
scope: {
myDisabled: '='
},
link: function(scope, element, attrs) {
var test = scope.$eval(attrs.myDisabled);
console.log(test);
scope.$watch(attrs.myDisabled, function (test) {
if (test) {
element.attr();
}
else {
element.attr('disabled', 'false');
}
});
}
};
});

AngularJS call method from controller in directive?

I have a problem: I use Angular and I need to use pushMsg method but I don't know how can I call it, boxCtrl.pushMsg(msg) does not work.
app.directive("fileread", function (socket) {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var msg = { author: 'me', class: 'me' };
// WHAT HERE???????
});
}
}
});
boxCtrl = function (socket, $scope) {
this.messages = [];
}
boxCtrl.prototype = {
pushMsg: function (message) {
this.messages.push(message);
}
}
app.controller('boxCtrl', boxCtrl);
You create an isolated scope and pass it as an attribute:
app.directive("fileread", function (socket) {
return {
scope: {
fileread: "=",
pushMessage: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var msg = { author: 'me', class: 'me' };
scope.pushMessage(msg);
});
}
}
});
And in your HTML:
<div fileread="..." push-message="pushMsg">
Edit: your controller should be something like this:
app.controller('Ctrl', function($scope) {
$scope.messages = [];
$scope.name = function(msg) {
$scope.messages.push(msg);
$scope.$apply(); //I think you need this to update the UI (not sure though)
}
})

why angularjs directive inherit the scope but doesn't change the scope variable?

(function () {
'use strict'
var pagesize = 5;
var memberManager = angular.module('memberManager',['mydirective'],function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
})
memberManager.constant('apiUri', {
getMembers: '/membermanage/get',
charge: '/membermanage/charge',
exchange: '/membermanage/exchange'
});
memberManager.factory('managerService',function ($http,apiUri) {
return {
getMembers: function (data) {
return $http.get(apiUri.getMembers,{ params: data });
},
charge: function (data) {
return $http.post(apiUri.charge,data);
},
exchange: function (data) {
return $http.post(apiUri.exchange,data);
}
}
});
memberManager.directive('modalWin',function () {
return {
restrict: 'A',
link: function (scope,elem,attrs) {
var modalWinId = attrs.targetid;
var clickHandler = function () {
var index = $(elem).attr('index');
scope.$apply(function () {
scope.itemIndex = parseInt(index);
scope.chargeModel.index = parseInt(index);
});
$('#' + modalWinId).modal();
scope.$on('http:cash',function () {
$('#' + modalWinId).modal('hide');
});
scope.$on('http:exchange',function () {
$('#' + modalWinId).modal('hide');
});
};
$(elem).bind('click',clickHandler);
}
}
})
memberManager.controller('manCtrl',function ($scope,managerService,$rootScope,managerHelper) {
$scope.isLoadingData = true;
$scope.chargeModel = {
index: 0,
cash_num: 0,
cash_store: '',
cash_stuff: ''
};
// which item to be edit?
$scope.itemIndex = 0;
$scope.test = {
index: 0
};
$scope.exchangeModel = {
exchange_number: 0,
exchange_way: 1,// 直接消费
exchange_store: '',
exchange_pass: ''
}
$scope.loader = {
exchange: false,
cash: false
};
$scope.exchange = function () {
alert($scope.itemIndex);
$scope.loader.exchange = true;
var data = {
exchange_number: $scope.exchangeModel.exchange_number,
exchange_wechat_id: $scope.model[$scope.itemIndex].wc_openid,
exchange_type: $scope.exchangeModel.exchange_type
};
console.log(data);
managerService.exchange(data).success(function (data) {
$scope.loader.exchange = false;
$rootScope.$broadcast('http:exchange');
$scope.getData($scope.currentPageIndex);
})
};
})();
Click event callbacks execute outside Angular world. You need to use $apply:
demo.directive('testD',function(){
return {
restrict: 'A',
link: function(scope,elem,attr){
$(elem).click(function(){
scope.$apply(function(){
scope.val = 5;
});
});
}
}
});
Fiddle
Try this :
var demo = angular('demo',[]);
demo.directive('testD',function(){
restrict: 'A',
scope: {
'val': '=' // here the fix
},
link: function(scope,elem,attr){
$(elem).click(function(){
scope.val = 5;
});
}
});
demo.controller('testCtrl',function($scope){
$scope.val = 0;
});

Categories