How to define a function inside angular ui modal controller - javascript

I try to define a function inside angular ui modal controller by default a found the two function $scope.ok and the $scope.cancel and I want to add my function that remove an item form a list of items that a send to that controller
This my angular ui modal controller code :
myapp.controller('ModalInstanceCtrl', function ($scope,$location,$uibModalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$uibModalInstance.close($scope.selected.item);
alert("redirection");
$location.path('/questionnaire');
};
$scope.closeListeChoix = function () {
$uibModalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
$scope.deleteChoix=function($index)
{
alert("supp")
$scope.items.splice($index, 1);
};
});
and here where I send the liste of items to modal controller
$scope.ListeChoixOneQuestion=[];
$scope.openListeChoix = function ($index) {
$scope.ListeChoixOneQuestion=$scope.questions[$index].choix ;
console.log("*********** choix de la question **********")
for(var i=0;i<$scope.ListeChoixOneQuestion.length;i++){
console.log("choix : "+$scope.ListeChoixOneQuestion[i].designation);
}
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'listeOfChoix.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function () {
return $scope.ListeChoixOneQuestion;
}
}
});
and this my html code when i call the function deleteChoix in my ng-click nothing happen and the item did not remove from the list of items
any solution
<div class="modal-body">
<div class="row">
<div class="table-responsive">
<table id="Table2" class="table table-bordered table-striped">
<thead>
<tr>
<th>Designation</th>
<th>Image</th>
<th>Aller à la question</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="choix in items track by $index">
<td>{{choix.designation}}</td>
<td>{{choix.imageUrl}}</td>
<td>{{choix.gotoQuestion}}</td>
<td class="text-center" style="width: 50px;">
<span class="btn btn-danger btn-xs fa fa-remove" style="cursor: pointer;" ng-click="deleteChoix($index);"></span>
</td>
<tr>
</tbody>
</table>
</div>
</div>
</div>

As said in comment the short solution is
$parent.deleteChoix($index);
It is a scope problem du to limit of inheritancy in Javascript.
If you don't want to have this problem, always use an inermediary object like :
$scope.context = {};// NEVER forget to initialize it in your controller or it won't work even if you don't put anything in at the start.
$scope.context.deleteChoix = [...];
So you won't need to wonder if you should use $parent or even $parent.$parent.
Check http://zcourts.com/2013/05/31/angularjs-if-you-dont-have-a-dot-youre-doing-it-wrong/ for more information.

Related

Custom directive inside ng-repeat

I have this custom directive.
I call my directive like bellow, inside a ng-repeat.
selectedMealCalc.calculated_foods as 'items', is an array of objects
<!-- DIRECTIVE -->
<div ng-repeat="option in [0,1,2,3,4]">
<meal-option option="{{option}}"
items="selectedMealCalc.calculated_foods"
selectedmealcalc="selectedMealCalc"></meal-option> </div>
<!-- DIRECTIVE -->
Then I created this directive in angularjs.
'use strict';
angular.module('nutriApp').directive('mealOption', ['$compile', function($compile) {
return {
restrict: 'E',
templateUrl: 'views/checkins/meal-options.html',
scope: {
option: "#",
items: "=",
selectedmealcalc: "="
},
controller: ['$scope', 'Food', function($scope, Food) {
$scope.sumFood = {};
$scope.summerizeOption = function(foods) {
if(foods.length > 0){
$scope.sumFood = Food.summerize(foods);
}
return $scope.sumFood;
};
}]
};
}]);
And this HTML directive.
<div class="row" ng-init="filteredItems = ( items | filter: { food_option: option } )" ng-controller="CheckinsPlansCtrl">
<div class="col-md-12" ng-show="filteredItems.length > 0">
Opção {{ option }}
<table class="table table-calculo table-striped">
<thead>
<tr>
<th>Alimento</th>
<th>Quantidade</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="foodCalculation in filteredItems track by $index">
<td>{{foodCalculation.food.name}}</td>
<td>{{foodCalculation.gram_amount}} g</td>
</tr>
</tbody>
</table>
</div>
</div>
When I update the selectedMealCalc.calculated_foods the custom directive is not updating.
I have to close the modal and open again in my page to saw the new line.
As this comment Custom directive inside ng-repeat in this post.
I removed the ng-init because ng-init: "Only to initialize a property on the scope. I would recommend not to use it." as this another answer Does ng-init watch over change on instantiated property like ng-model does?

Passing ng-click value to one controller and use it in another controller

I am using a table and a button inside the table pops up a modal. I want to pass the Id value in that row to the modal controller so that I can use it to pass it to the the rest api call and then subsequently load valus in the modal table.
App.js
var app = angular.module("UiApp", ["ServiceApp"]);
app.service('sharedProperties', function () {
var idValue = 'test string value';
return {
getId: function () {
return idValue;
},
setId: function (value) {
idValue = value;
}
}
});
app.controller("PortFolioController", function ($scope, GetPortfolios,sharedProperties) {
$scope.Portfolios = GetPortfolios.query({ pmid: 2 });
console.log($scope.Portfolios);
$scope.addOrder = function (id) {
sharedProperties.setId(id)
};
});
app.controller("OrderController", function ($scope, GetOrders,sharedProperties) {
$scope.item = sharedProperties.getId();
$scope.Orders = GetOrders.query({ id: item});
});
Service.js
var app = angular.module("ServiceApp", ["ngResource"]);
app.factory('GetPortfolios', function ($resource) {
return $resource("http://localhost:61347/api/PortfolioManager/GetPortfolios/");
});
app.factory('GetOrders', function ($resource) {
return $resource("http://localhost:61347/api/PortfolioManager/GetPortfolioOrders/");
});
HTML
<div >
<table class="table table-striped table-hover table-bordered" id="editable-sample" ng-controller="PortFolioController">
<thead>
<tr>
<th>Portfolio ID</th>
<th>Portfolio Name</th>
<th>Portfolio Type</th>
<th>Portfolio Description</th>
<th>Show Stocks</th>
</tr>
</thead>
<tbody>
<tr class="" ng-repeat="portfolio in Portfolios">
<td>{{portfolio.portfolioId}}</td>
<td>{{portfolio.portfolioName}}</td>
<td>{{portfolio.type}}</td>
<td>{{portfolio.description}}</td>
<td> <button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#myModal" ng-click="addOrder(portfolio.portfolioId)" >Show <i class="fa fa-info-circle"></i></button></td>
</tr>
</tbody>
</table>
</div>
</div>
<!--Modal start-->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">My Portfolio</h4>
</div>
<div class="modal-body">
<h3>Stock List</h3>
<div class="space15"></div>
<table class="table table-striped table-hover table-bordered" id="editable-sample" ng-controller="OrderController">
<thead>
<tr>
<th>Symbol</th>
<th>Stock Name</th>
<th>Quantity</th>
<th>Market Price</th>
</tr>
</thead>
<tbody>
<tr class="" ng-repeat="order in Orders">
<td>{{order.symbol}}</td>
<td>{{order.executedQuantity}}</td>
<td>{{order.price}}</td>
<td>{{order.createTStamp}}</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close <i class="fa fa-times"></i></button>
</div>
In PortFolioController Controller, you can do:
$rootScope.$broadcast('eventName', id);
and listen to the event in OrderController Controller:
$scope.$on('eventName', function (event, id) {...});
Also you can use AngularJS Service Passing Data Between Controllers to see some examples
or the simpleset way without any service is to use $rootScope and $broadcast an event from one Controller and listen to it in the other Controller
thus, No need of writing an extra service sharedProperties
Something like this :-
app.controller("PortFolioController", function ($scope, GetPortfolios,$rootScope) {
//Other Codes
$scope.addOrder = function (id) {
$rootScope.$broadcast('ID-Clicked', { Id: id});
};
}
app.controller("OrderController", function ($scope, GetOrders,$rootScope) {
//Other Codes
//Listen for the event
$rootScope.$on('ID-Clicked', function(event, data){
$scope.item = data.Id;// data.Id has the Clicked Id
});
}
This approach can be done using 2 ways.
First Way is to broadcast some events from the parent rootscope instance and capture that on the $scope elements.This format is not considered as a good way of coding.
Secondly, to communicate data between controllers use a service.Yeah you are currently on the right,clean & widely accepted path.
Remember that services are singletons.so once instansiated it is available to all controllers.But the challenge here is as soon as you click on button element your service sets your idValue in the service.Now how does the second controller know that.The answer would be register a $watch service to watch if the idValue in the service is changed as below.
app.controller("OrderController", function ($scope, GetOrders, sharedProperties) {
$scope.$watch(function () {
return sharedProperties.getId()
}, function (newValue, oldValue) {
if (newValue != oldValue) {
$scope.item = newValue;
$scope.Orders = GetOrders.query({ id: item });
}
});
});

ng-click not working in bootstrap popover content

I want to show a clickable table in my popover, and call a function when one of the rows get clicked. My html looks like this:
<a popover id="showDays"
type="button"
class="btn btn-success btn-xs pull-left"
data-toggle="popover"
data-placement="right"
data-html="true"
title="Popover title"
data-content=
'<table class="table table-condensed">
<tbody>
<tr ng-repeat="d in days" ng-click="show(111)">
<td ng-bind="d"></td>
<td ng-bind="x"></td>
</tr>
</tbody>
</table>'>
<i class="fa fa-clock-o fa-lg">Click me</i>
</a>
And my script.js:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.days = [
'Sunday',
'Monday',
];
$scope.show = function(x) {
console.log("show called with " + x);
$scope.x = x;
}
}).directive('popover', function($compile, $timeout){
return {
restrict: 'A',
link:function(scope, el, attrs){
var content = attrs.content;
var elm = angular.element('<div />');
elm.append(attrs.content);
$compile(elm)(scope);
$timeout(function() {
el.removeAttr('popover').attr('data-content',elm.html());
el.popover();
});
}
}
});
Demo here
The code was copied from this question, the answer itself works fine, but my show function is not called. Any idea why?
I've found the problem, for some reason the directive failed to bind function show with scope, but succeeded with days, I have experimented with a few things, if I change the way the link function is written, ng-click will work, but not ng-repeat, which means it had failed to bind days in that case.
The updated DEMO uses templateUrl instead of the data-content attribute
<script type="text/ng-template" id="popover-content">
<table class="table table-condensed">
<tbody>
<tr ng-repeat="d in days" role="button" ng-click="show(111)">
<td ng-bind="d"></td>
<td ng-bind="x"></td>
</tr>
</tbody>
</table>
</script>
now both ng-repeat and ng-click work fine for me.

Failed initializing html tab with server data

I am creating an html page with two tabs. When you click on tab 1, it loads table data 1. When you click on tab 2,
it loads table data 2. Tab 1 is working as expected. However, when I click on tab 2, the data isn't loaded. The controllers
are identical. What is the difference?
Here is the relevant html code. tab with id "tableData" loads with data and tab with id "correlations" doesn't load.
<div>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation">Table Data</li>
<li role="presentation">Correlations</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="tableData">
<h2 class="sub-header">Health Data</h2>
<div class="table-responsive" data-ng-app="myApp" data-ng-controller="journalCtrl">
<div data-ng-include="'screens/tablescreen.html'"></div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="correlations">
<h2 class="sub-header">Correlations Data</h2>
<div class="table-responsive" data-ng-app="correlationsApp" data-ng-controller="correlationsCtrl">
<div data-ng-include="'screens/tablescreen.html'"></div>
</div>
</div>
</div>
</div>
Here is my correlationsCtrl. init() is never invoked. Why?:
var correlationsApp = angular.module('correlationsApp', []);
correlationsApp.controller('correlationsCtrl', function ($scope, $http) {
$scope.init = function () {
$http.get("https://localhost:4567/foo/1/correlations")
.then(function (response) {
var json = response.data.records;
$scope.records = json;
$scope.headers = response.data.headers;
});
};
//This is not invoked. Why?
$scope.init();
});
Here is my controller which does get invoked:
var app = angular.module('myApp', []);
app.controller('journalCtrl', function ($scope, $http) {
$scope.init = function () {
$http.get("https://localhost:4567/journal/1")
.then(function (response) {
var json = response.data.records;
$scope.records = json;
$scope.headers = response.data.headers;
});
};
//This is invoked on page load. Why does this work and the other doesn't?
$scope.init();
});
Here is the html table:
<table class="table table-striped">
<thead>
<tr>
<th data-ng-repeat="header in headers">{{header}}</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="record in records track by $index">
<td data-ng-repeat="header in headers">{{ record.data[header] }}</td>
</tr>
</tbody>
</table>
In html you declare data-ng-controller="fooCtrl" but you have no controller fooCtrl. No need to declare two different module for two tabs you can declare two controller for two tabs in same module.
like:
var app = angular.module('myApp',[]);
app.controller('correlationsCtrl', function ($scope, $http) {
$scope.init = function () {
// your code
};
$scope.init();
}).controller('journalCtrl', function ($scope, $http) {
$scope.init = function () {
// your code
};
$scope.init();
});
so you use ng-app = "myApp" in root element like <html ng-app="myApp"> or <body ng-app="myApp"> and use only data-ng-controller in your tab page.
<div class="table-responsive" data-ng-controller="journalCtrl">
<div data-ng-include="'screens/tablescreen.html'"></div>
</div>
and
<div class="table-responsive" data-ng-controller="correlationsCtrl">
<div data-ng-include="'screens/tablescreen.html'"></div>
</div>
See PLUNKER DEMO two tabs show data from two different controllers.

Angular ng-click load controller

I'm trying to practice angular and I'm stuck this this.
How do I make ng-click load the displayController? Or am I doing this wrong way?
The Angular
var bible = angular.module('bible', []);
// Load the Books
bible.controller('listController', ['$scope', '$http', function($scope, $http) {
$http.get('books.json').success(function(data) {
$scope.books = data
});
}]);
bible.controller('displayController', function($scope) {
$scope.test = "TEST TEXT";
});
The HTML
<div class="row">
<div class="col-md-12" ng-controller="listController">
<table class="table">
<thead>
<th>Testament</th>
<th>Title</th>
<th>Chapters</th>
</thead>
<tbody>
<tr ng-repeat="book in books">
<td>{{book.testament}}</td>
<td>{{book.title}}</td>
<td>{{book.chapters}}</td>
</tr>
</tbody>
</table>
<div class="display-book" ng-controller="displayController">
{{test}}
</div>
</div>
</div>
You don't need the additional controller there. I guess you want to display additional infos about the clicked book.
Use a reference and ngIf
var bible = angular.module('bible', []);
// Load the Books
bible.controller('listController', ['$scope', '$http', function($scope, $http) {
$scope.selectedBook = null;
$http.get('books.json').success(function(data) {
$scope.books = data
});
}]);
And html:
<div class="row">
<div class="col-md-12" ng-controller="listController">
<!-- will be shown, as long as not book is selected -->
<table data-ng-if="selectedBook == null" class="table">
<thead>
<th>Testament</th>
<th>Title</th>
<th>Chapters</th>
</thead>
<tbody>
<tr ng-repeat="book in books">
<td>{{book.testament}}</td>
<td>{{book.title}}</td>
<td>{{book.chapters}}</td>
</tr>
</tbody>
</table>
<!-- will be shown, when a book got selected -->
<div data-ng-if="selectedBook != null" class="display-book">
<!-- display the selection table again -->
<button data-ng-click="selectedBook = null">Back</button>
{{selectedBook.title}}
</div>
</div>
</div>
Why do you want to call a separate controller cant you implement the functionality in a separate function like below ,
bible.controller('listController', ['$scope', '$http', function($scope, $http) {
$http.get('books.json').success(function(data) {
$scope.books = data
});
$scope.display = function(){
// **YOUR CODE COMES HERE**
}
}]);
<td>{{book.title}}</td>

Categories

Resources