Angular ng-click load controller - javascript

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>

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?

Load Data from Database Without Blinking Angular Js

Am loading data from database to a table in html with angualar js. am also using interval so as to make the table reload every 10 seconds to get new data that has just been inputed by other users.
Problem:
The table blinks every time it reloads. making the page look funny like it has a glitch.
What am looking for:
Is there a way i can make the new data just slide in from the top of the table and become number one while the rest re adjust underneath it And become number two, three and so on. i was made to believe Angular Js is magical reason why i opted for it instead of using my usual AJAX
Angular Code
var supDetails = angular.module("supDetails", ['datatables']);
supDetails.controller('supportController', function($scope, $http, $interval) {
$scope.names = [];
$scope.isFirst = true;
$scope.loadData = function() {
var httpRequest = $http({
method: 'GET',
url: 'anfil.php?ins=sup'
}).success(function(data, status) {
console.log('loading..');
$scope.names = data;
if(!$scope.isFirst){
angular.forEach(data,function(key,val){
$scope.names[key] = data[key];
});
}
$scope.isFirst = false;
});
};
$scope.loadData();
// Function to replicate setInterval using $timeout service.
$interval(function () {
$scope.loadData();
}, 10000);
});
My HTML
<!-- /.col -->
<div class="col-md-9" ng-app = "supDetails" ng-controller="supportController">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Messages</h3>
<!-- /.box-tools -->
<div class="box-tools pull-right">
<div class="has-feedback">
<button type="button" ng-click="loadData()" class="btn btn-default btn-sm"><i class="fa fa-refresh"></i></button>
</div>
</div>
</div>
<!-- /.box-header -->
<div class="box-body no-padding">
<div class="mailbox-messages">
<table datatable="ng" class="table table-hover table-striped">
<thead>
<tr>
<th>Stat</th>
<th>Name</th>
<th>Problem</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in names">
<td class="mailbox-star"><i class="fa fa-circle text-blue"></i></td>
<td class="mailbox-name">{{x.user_id}}</td>
<td class="mailbox-subject"><b>{{x.ticket_title}}</b> - {{x.subject}}
</td>
<td class="mailbox-date">{{x.ticket_open_date}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Stat</th>
<th>Name</th>
<th>Problem</th>
<th>Time</th>
</tr>
</tfoot>
</table>
<!-- /.table -->
</div>
<!-- /.mail-box-messages -->
</div>
<!-- /.box-body -->
</div>
<!-- /. box -->
</div>
<!-- /.col -->
I think its your css problem which doesn't have a minimum height as you can see in this snippet its not blinking..
If you still want data to appear slide from up to down, You can uncomment the code in the answer, in this way it will remove row one by one from the table and replace it with the new one.
var app = angular.module('myApp', []);
function PeopleCtrl($scope, $http,$interval) {
$scope.people = [];
$scope.isFirst = true;
$scope.loadPeople = function() {
var httpRequest = $http({
method: 'GET',
url: 'https://jsonplaceholder.typicode.com/users'
}).success(function(data, status) {
console.log('loading..');
$scope.people = data;
/* if(!$scope.isFirst){
angular.forEach(data,function(val,key){
$scope.people[key] = data[key];
});
}
$scope.isFirst = false;*/
});
};
$scope.loadPeople();
$interval(function () {
$scope.loadPeople();
}, 10000);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div ng-app="myApp">
<div ng-controller="PeopleCtrl">
<table class="table">
<tr>
<th>Id</th>
<th>Name</th>
<th>UserNmae</th>
</tr>
<tr ng-repeat="person in people">
<td>{{person.id}}</td>
<td>{{person.name}}</td>
<td>{{person.username}}</td>
</tr>
</table>
</div>
</div>
There are a few ways to solve your problems:
1) Write algorithm, that load your data then compare it with existing data. If there any diffs you, should add just new records to your table.
2) Use WebSockets, they will give you ability to get from server only new records in real-time.

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 });
}
});
});

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.

Error: [ng:areq] Argument 'ActsController' is not a function, got undefined

I keep getting the error: Error: [ng:areq] Argument 'ActsController' is not a function, got undefined. I've seen several other people have similar errors, usually due to typos. But I don't think I've misspelled the controller name anywhere.
I am working with Angular and Rails, by the way.
app.js
var controllers, snowball_effect;
snowball_effect = angular.module('snowball_effect', [
'templates',
'ngRoute',
'ngResource',
'controllers'
]);
snowball_effect.config([
'$routeProvider', function($routeProvider) {
return $routeProvider
.when('/', {
templateUrl: "static_pages/index.html",
controller: 'StaticPagesController'
})
.when('/acts/index', {
templateUrl: "acts/index.html",
controller: 'ActsController'
});
}
]);
controllers = angular.module('controllers', []);
controllers.controller("StaticPagesController", ['$scope', function($scope) {}]);
controllers.controller("ActsController", [
'$scope',
'$routeParams',
'$location',
'$resource',
function($scope,$routeParams,$location,$resource) {
$scope.acts = [
{
id: 1,
name: "Plant a Flower",
description: "Plant a flower in your garden or along the street."
inspires: 1
}
];
}]);
javascript/templates/acts/index.html
<div class="actions_body">
<h2>Listing Actions</h2>
<div ng-controller="ActsController" class="body">
<table class="row">
<thead>
<tr>
<th class="col-md-offset-1 col-md-2 active">
<label>Name</label>
</th>
<th class="col-md-4">Description</th>
<th class="col-md-2">Inspires</th>
<th colspan="2" class="col-md-2">Modify</th>
</tr>
</thead>
<tbody ng-repeat="act in acts">
<td class="col-md-offset-1 col-md-2">{{act.name}}</td>
<td class="col-md-4">{{act.description}}</td>
<td class="col-md-2">{{act.inspires}}</td>
<td>Edit</td>
<td>Delete</td>
</tbody>
</table>
<br>
New Action
</div>
</div>
Edit:
Now that I think about it, I'm also having another problem. Whenever I refresh the page, the main partial vanishes. I guess this question is more Rails/Angular specific.
views/home/index.html.erb
<div ng-app="snowball_effect">
<div class="view-container">
<div ng-include="'layouts/index.html'"></div>
</div>
</div>
assets/javascript/templates/layouts/index.html
<div ng-include="'layouts/navigation.html'"></div>
<div ng-view class="view-frame animate-view"></div>
assets/javascript/templates/static_pages/index.html
<div class="body">
<div class="container">
<div class="introduction">
<h1>Welcome to Snowball Effect</h1>
</div>
<div class="body">
<h2>A social media platform that brings people together in a spirit of community service.</h2>
</div>
</div>
</div>
So, in the layout/index.html, the navigation bar loads fine, but the ng-view only after the first page load.
Is app.js included in index.html??
<script src="js/app.js"></script>

Categories

Resources