How do I get $emit to controller from directive built html - javascript

I'm having difficulty figuring this out. I have a directive building html from promise data. For each row, it's adding buttons for CRUD operations. I do not know how to get the button event to trigger in my controller. Regardless of how my controller is set up, how can I get the event to register in my controller? I am currently trying $emit, but nothing seems to happen.
Directive generated html:
controls = controls+'<button type="button" data-tooltip-placement="bottom" data-tooltip="'+action.name+'" ng-click="$emit(&apos;'+action.broadcaster+'&apos;,'+rowId+')" name="'+action.name+'" class="btn btn-xs btn-default ng-scope"><i class="'+action.icon+'"></i> </button>'
How it looks in Chrome tools:
<button type="button" data-tooltip-placement="bottom" data-tooltip="delete" ng-click="$emit('removeOrgCourse',134)" name="delete" class="btn btn-xs btn-default ng-scope"><i class="fa fa-trash-o"></i> </button>
and my controller listener:
$scope.$on('removeOrgCourse', function( event, data ){
console.log(data);
});
UPDATE:
Just changed the ng-click to console.log("click") and nothing happened. So the issue is that ng-click is not registering;

While you can use events in angular to achive that, one other option is to use & expression scope binding to pass controller method to directive. Example code (from egghead.io)(see working code at jsbin):
<div ng-app="phoneApp">
<!-- we've replaced the use of $scope with the preferred "controller as" syntax. see:http://toddmotto.com/digging-into-angulars-controller-as-syntax/ -->
<div ng-controller="AppCtrl as appctrl">
<div phone dial="appctrl.callHome(message)"></div>
<div phone dial="appctrl.callHome(message)"></div>
<div phone dial="appctrl.callHome(message)"></div>
</div>
Controller:
app.controller("AppCtrl", function() {
var appctrl = this;
appctrl.callHome = function(message) {
alert(message);
};
});
And directive:
app.directive("phone", function() {
return {
scope: {
dial: "&"
},
template: '<input type="text" ng-model="value">' +
'<div class="button" ng-click="dial({message:value})">Call home!</div>'
};
});

Maybe you have to use $broadcast, depends if the controllers are on the same level or who's over who.
Working with $scope.$emit and $scope.$on
http://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/
in the secon link you can put the $emit and $broadcast in the same controller and see whad do you catch in you $on

Related

ng-model not binding to input data within ng-repeat

Using AngularJs 1.6.7, I have created a table which pulls project details from a database and displays these details within a table. Each row has a modify/update button using ng-show/hide. When modify is clicked, the div changes to editable input fields, when update is clicked, the new input data will be update in the database.
I am trying to access input items within an ng-repeat and using ng-model to bind the input to update projects in a database using Flask.
The problem is that when I access the data in AJS once update is clicked, no data has binded to the new input values.
My HTML looks like this.
<tr data-ng-repeat="(key, value) in projects" >
<td>
<div data-ng-hide="edditable_project[value.project_name]">{[value.project_name]}
</div>
<div data-ng-show="edditable_project[value.project_name]">
<input class="form-control" data-mg-model="updatedProjectName" value="{[value.project_name]}">
</div>
</td>
<td>
<button class="btn btn-danger add-on pull-right btn-sm" data-ng-click="removeProject(value)">Delete</button>
<button class="btn btn-primary add-on btn-sm pull-right" data-ng-hide="edditable_project[value.project_name]" data-ng-click="modify(value.project_name)">Modify</button>
<button type="submit" class="btn btn-success pull-right btn-sm " data-ng-show="edditable_project[value.project_name]" data-ng-click="update(value)">Update</button>
</td>
</tr>
And my controller looks like this:
app.controller('projectSettingsController', ['$scope', '$http', function($scope, $http) {
$scope.modify = function(project) {
$scope.edditable_project[project] = true;
};
$scope.update = function(project) {
data = {
project_name: $scope.updatedProjectName,
}
console.log($scope.updatedProjectName);
// Update project.
$http.post('/api/project/update-project', data).then(function(response) {
toastr.success(response.data);
});
$http.get('/api/project/get-all-project-details').then(function (response) {
$scope.projects = response.data;
});
$scope.edditable_project[project] = false;
};
}]);
The current output for ng-model="updatedProjectName" is undefined.
Am I doing something wrong within the scope?
well you should define your binding vairable in the scope of your controller like
$scope.updatedProjectName =""; by default it`s null as you have described, but for all your inputs you will have one data binding, i think you should have some
$scope.data={};
tr data-ng-repeat="(key, value) in projects" >
<input data-ng-model="data[key]">
</tr>
and you don`t need to set value in your input, ng-model will make it for you
You are trying to access a variable which is defined inside of ng-repeat's scope. What you would want to do in this case is pass value and work on the project variable inside the update function.
Change your mark up to data-mg-model="value.project_name". Now the ng-model binds to same. When the update completes set the latest data(if needed) as properties on project. It will reflect in the view because of 2 way data binding
Inside update you should do as follows
$scope.update = function(project) {
// Update project.
$http.post('/api/project/update-project', project).then(function(response) {
toastr.success(response.data);
// If needed set new properties on the project variable
// based on the response
});
}
You seem to have a typo:
<input class="form-control" data-mg-model="updatedProjectName" value="{[value.project_name]}">
Use ng-model instead of mg-model.

ng-click on button that is ng-included

I have a problem. I'm trying to include a button that's on a html template page on to my index.html page. I do it like this
<ng-include src="'logout/logout.template.html'"></ng-include>
The page is:
<button type="button" class="btn btn-default btn-sm" ng-click="$ctrl.lala()">
<span class="glyphicon glyphicon-log-out" ></span> Log out
</button>
The problem is, the thing doesn't work. It won't access the ctrl function. As I read, ng-include doesn't work well with other angular directives so my question is, how else can I include my button template in the index.html without copy pasting the code because it's connected to a componenet an dservice so I can't break it.
The componenent:
'use strict';
angular
.module('logout')
.component('logout', {
templateUrl: 'logout/logout.template.html',
controller: ['$scope', '$location', '$localStorage', 'Logout',
function LogoutController($scope, $location, $localStorage, Logout) {
this.lala = function () {
console.log("doing logout");
}
}
]
});
I know it sounds like an overkill, but I would just create another component for it. If lala() is the function that actually logs the user out then it's best to include that in the component too, so you don't have to repeat it in every parent component.
Take a look at this jsfiddle for a complete sample. I wrote everything in the html, but I copied the important part below:
https://jsfiddle.net/6cjd5ggq/1/
<logout></logout>
angular.module('logoutapp')
.controller('logoutController', logoutController)
.component('logout', {
// you can use templateUrl, but it's easier this way in jsfiddle
template: `<button type="button" class="btn btn-default btn-sm" ng-click="$ctrl.lala()">
<span class="glyphicon glyphicon-log-out"></span> Log out
</button>`,
controller: 'logoutController'
});
function logoutController() {
this.lala = function() {
alert("logout!");
};
}

ng-click does not work

I'm programming a single-page web application, mostly using the AngularJS framework, and am encountering a problem while using the ng-click directive.
This directive actually does nothing upon click. The linked method is not called (I can't debug it).
Below the code in question:
template file:
<div ng-controller="BonusCtrl as bonusManager">
<!-- [...] -->
<button style="margin-top: 5px"
class="btn btn-success" ng-click="add()"><i class="fa fa-plus"/> Règle de calcul</button>
<!-- [...] -->
</div>
controller:
idServerApp.controller('BonusCtrl', ['$scope', 'webService', 'math', 'DATERANGE_OPTIONS', function ($scope, webService, math, DATERANGE_OPTIONS) {
$scope.add = function() {
console.log('foo'); // no call
var newItem = {
brandId: undefined,
days: 0,
priceMinEVAT: 0,
bonus: 0
};
$scope.rules.push(newItem);
};
Do you have any idea of the problem?
Edit 1
I tried to replace bonusManager.add() by add() and BonusCtrl.add().
I then tried to replace $scope by this, or to remove the controllerAs.
Complete JSFiddle (using some of my services)
Edit 2
Thanks for your answers. I found the solution myself, and it was crappy.
I forgot a closing div tag in the HTML template, so the controller was not defined.
I get your code and made an running example with two cases.
First one using BonusCtrl
$scope.add = function () {...}
ng-click="add()"
And second with bonusManager
this.add = function () {...}
ng-click="bonusManager.add()"
For me it should works just fine. Please let me know if you have any other issues.
var app = angular.module('myapp',[]);
app.controller('BonusCtrl', ['$scope', function ($scope) {
$scope.add = function() {
console.log('Hey you\'ve just invoked add() function!'); // no call
var newItem = {
brandId: undefined,
days: 0,
priceMinEVAT: 0,
bonus: 0
};
};
this.add = function () {
console.log('You can invoke function using \' bonusManager.add()'); // no call
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<h1>NG-CLICK EXAMPLE</h1>
<div ng-controller="BonusCtrl as bonusManager">
<button style="margin-top: 5px"
class="btn btn-success" ng-click="add()"><i class="fa fa-plus"/>add()</button>
<button style="margin-top: 5px"
class="btn btn-success" ng-click="bonusManager.add()"><i class="fa fa-plus"/> bounsManager.add()</button>
</div>
</div>
However you can always use your
Check the working demo: JSFidde
You are using <div ng-controller="BonusCtrl as bonusManager">, so call it like:
<button style="margin-top: 5px" class="btn btn-success"
ng-submit="bonusManager.add()"><i class="fa fa-plus"/> Règle de calcul</button>
In the controller, define this.add = function() {... instead of $scope.add = function() {.... Because the keyword as will call a new BonusCtrl() under the hood.
If you use $scope than you don't need construction ControllerAs, just use
<div ng-controller="BonusCtrl">
and submit function ng-submit="add()"
Or if you want to use ControllerAs, than use "this":
<div ng-controller="BonusCtrl as bonusManager">
ng-submit="BonusCtrl.add()"
But in your controller have to be "this" instead of $scope:
`
this.add = function() {
`
Try it.
If you are using BonusCtrl as bonusManager then do as follows
Update bonusManager.add() in view and in controller write this.add instead of $scope.add() .
Otherwise just remove as bonusManager from ng -controller syntax .it will work fine.

Can't update $rootScope value after submit action

I'm a beginner with AngularJS. However, I can't update $rootScope value after submit a form, it's being returned as undefined.
The Controller:
app.controller('campaignCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.submit = function() {
$rootScope.campaign = this.campaign;
};
}]);
And the form:
<form class="holder" name="campaignForm" ng-submit="submit()" >
<div class="form-group" show-errors>
<label for="inputDate">Date</label>
<p class="help-block"><em>Ex: 12/10/2015</em></p>
<input type="date" class="form-control" name="inputDate" ng-model="campaign.date" id="inputDate" required>
</div>
<button type="submit" class="btn btn-lg btn-default pull-right">Submit</button>
</form>
I used your code and added a $watch on $rootScope.campaign and it worked great.
.controller('someController', function($scope, $rootScope) {
$scope.submit = function() {
$rootScope.campaign = $scope.campaign;
};
$rootScope.$watch('campaign', function(newVal, oldVal) {
if(newVal !== oldVal) {
console.log("New Val = ");
console.log(newVal);
}
});
});
JSFiddle
If you are looking for something that persists across a page refresh, that is not $rootScope. Look at something like this: AngualrJS: sustaining data on html refresh
Check this. Your code seems correct except that you are missing closing tag on the input
`http://jsfiddle.net/ashishmusale/2001cf6r/`
Try
$scope.submit = function() {
$rootScope.campaign = $scope.campaign;
};
EDIT:
Try removing type="submit" from your button. It could be that your handler doesn't get called because the browser handles the form submission automatically (although you could verify that by putting a log in that function).
<button class="btn btn-lg btn-default pull-right">Submit</button>
EDIT 2:
Per our conversation via comments: $rootScope doesn't persist across requests. You'll need to store it somewhere permanent (like local storage or a cookie) or pass it to the server and then back to the client if you want to hold on to that value. I bet if you add a log inside that $scope.submit function, it will have a value there.

How can you pass a bound variable to an ng-click function?

I have a simple delete button that will accept a string or number but won't accept an ng-model variable ( not sure if that's the correct terminology ).
<button class="btn btn-danger" ng-click="delete('{{submission.id}}')">delete</button>
Which generates:
<button class="btn btn-danger" ng-click="delete('503a9742d6df30dd77000001')">delete</button>
However, nothing happens when I click. If I hard code a variable then it works just fine. I assume I'm just not doing things the "Angular" way, but I'm not sure what that way is :)
Here's my controller code:
$scope.delete = function ( id ) {
alert( 'delete ' + id );
}
You don't need to use curly brackets ({{}}) in the ng-click, try this:
<button class="btn btn-danger" ng-click="delete(submission.id)">delete</button>
The ngClick directive binds an expression. It executes Angular code directly (as ngIf, ngChange, etc.) without the need of {{ }}.
angular.module('app', []).controller('MyCtrl', function($scope) {
$scope.submission = { id: 100 };
$scope.delete = function(id) {
alert(id + " deleted!");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<button ng-click="delete(submission.id)">Delete</button>
</div>

Categories

Resources