AngularJS Refresh ng-repeat in other controller - html

My code is simple. I need to refresh a ng-repeat.
HTML
<div class="quick-actions" ng-controller="DashboardController">
<div class="ui accordion segment">
<div class="ui top attached label active title">
<?php echo __('My Tasks'); ?>
<i class="minus icon"></i>
</div>
<div class="active content">
<div class="ui items" ng-show="myTasks" id="myTasks">
<!-- Creacion de Items de los Taks -->
<div class="item" ng-repeat="T in myTasks">
<div class="content">
<a class="header" href="/angular/#/task/{{ T.Task.id }}">
{{ T.Task.name }}
</a>
<div class="meta">
{{ T.Task.due_date | date : 'dd-MMM-yyyy' }}
</div>
<div class="extra high-priority" ng-if="T.Task.priority == 50">
<i class="circle icon"></i>
<?php echo __('High'); ?>
</div>
<div class="extra medium-priority" ng-if="T.Task.priority == 25">
<i class="circle icon"></i>
<?php echo __('Medium'); ?>
</div>
<div class="extra low-priority" ng-if="T.Task.priority == 0">
<i class="circle icon"></i>
<?php echo __('Low'); ?>
</div>
</div>
</div>
<!-- Termina Creacion de los Items -->
</div>
</div>
</div>
</div>
When income is well DashboardController in angularjs load ng-repeat. Data is correct here.
.controller('DashboardController', function ($scope, $state, $rootScope, $stateParams, $q, $timeout, $http, $sce, $location, Sesion, Dashboard, Fullscreen) {
Dashboard.get_all_tasks().then(function (response) {
$scope.myTasks = response;
});
})
What I need is that when I'm in another controller I can update this ng-repeat. It does not work (data incorrect) here.
.controller('NewTaskController', function ($scope, $state, $rootScope, $stateParams, $q, $timeout, $http, $sce, Sesion, Users, Opportunities, Dashboard) {
Dashboard.get_all_tasks().then(function (response) {
$timeout(function () {
$scope.$apply(function () {
$scope.myTasks = response;
});
});
});
})
Any idea what I'm doing wrong?

You need to implement a service to pass data between controllers. Here is a simplified example. It is in this plunkr here to play with.
var projectModule = angular.module('project',[]);
projectModule.factory('Service', function() {
return {
thing : {
x : 100
}
};
});
function FirstCtrl($scope, Service) {
$scope.thing = Service.thing;
$scope.name = "First Controller";
}
function SecondCtrl($scope, Service) {
$scope.foo = Service.thing;
$scope.name = "Second Controller!";
}
In this way $scope.thing from the first controller is linked to scope.foo in the second controller via the service using thing
You will need to define the structure of myTasks in the service you define so that all the elements gets passed correctly.
Try implementing this into your project and if you have a specific hangup comment here and we will help but I don't know all your code or structure of myTasks so I'm not giving copy/paste code.

Related

Run controller only first time tab was clicked - AngularJS

I'm developing a website for our company, and one of the pages contains several tabs :
I want the loading operation to be done for each tab only once and not every time I click it, because these tabs have some API calls, and reloading takes time.
What is the best way to do it? I'm using Ui-router and ui-sref to move between each tab :
<div class="col-xs-2">
<div class="panel panel-default">
<div class="list-group panel panel-default">
<a ui-sref="dashboards.firstTab" ui-sref-active="active" class="list-group-item" id="firstTab_button">
<i style="color:darkblue" class="fa fa-area-chart"></i> TAB1 </a>
<a ui-sref="dashboards.secondTab" ui-sref-active="active" class="list-group-item" id="secondTab_button">
<i style="color:darkblue" class="fa fa-line-chart"></i> TAB2 </a>
<a ui-sref="dashboards.thirdTab" ui-sref-active="active" class="list-group-item" id="thirdTab_button">
<i style="color:darkblue" class="fa fa-server"></i> TAB3 </a>
</div>
</div>
</div>
<div ui-view class="col-xs-12">
<div class="row">
<div class="col-xs-12" ng-if="vm.isTabOneSelected">
<div ng-include src="'components/Cards/Tabs/TabOne/TabOne.html'"></div>
</div>
</div>
<div class="row">
<div class="col-xs-12" ng-if="vm.isTabTwoSelected">
<div ng-include src="'components/Cards/Tabs/TabTwo/TabTwo.html'"></div>
</div>
</div>
<div class="row">
<div class="col-xs-12" ng-if="vm.isTabThreeSelected">
<graph-panel panel-title="TabThree {{vm.isTabThreeSelected}}" chart-config="vm.charts.TabOneChartSite"></graph-panel>
</div>
</div>
</div>
On Each Controller, You can cache your loaded data in a service, and when you load your controller you will start by checking this service if it does not have the data, then you will request it from your APIs , in this case you only request your data once you access the tab for the first time :
eg. your service
app.service('dataService', function() {
this.firstTabData = null;
this.getFirstTabData = function () {
return this.firstTabData;
};
this.setFirstTabData = function (data) {
this.firstTabData = data;
};
});
your controller
app.controller('tabOne', function($scope, dataService) {
$scope.data = {};
$scope.load = function () {
if(dataService.getFirstTabData()) {
$scope.data = dataService.getFirstTabData();
}
else {
$scope.data = getDataFromAPI();
}
};
var getDataFromAPI = function () {
//get your data
dataService.setFirstTabData(dataFromAPI);
};
});

show glyphicon based on value in angular

my controller :
.controller('BlogController', function(blogFactory, $routeParams, $scope){
var that=this;
stat=false;
this.checkbookmark = function(bId){
console.log(bId)
blogFactory.checkBookmark(bId, function(response){
console.log(response)
if(response == "bookmarked"){
that.stat = true;
}
else{
that.stat = false;
}
})
}
my html code :
<div class="container" ng-controller="BlogController as blogCtrl">
<div class="row" ng-repeat="chunk in blogCtrl.blogs | filter: filter_name | orderBy:'-created_at' | groupBy: 3">
<div class="outerbox1 col-sm-4" ng-repeat="blog in chunk" >
<div class="innerbox3" ng-init="blogCtrl.checkbookmark(blog._id)">
<br>
<div> > READ MORE
<a ng-if="blogCtrl.stat" ng-href="#" ng-click="blogCtrl.removebookmark(blog._id)" class="glyphicon glyphicon-heart pull-right">{{blogCtrl.stat}}</a>
<a ng-if="!blogCtrl.stat" ng-href="#" ng-click="blogCtrl.addbookmark(blog._id)" class="glyphicon glyphicon-heart-empty pull-right">{{blogCtrl.stat}}</a>
</div>
</div>
</div>
</div>
</div>
service factory :
factory.checkBookmark = function(info, callback){
$http({
url:'api/check_bookmark_blog',
method:'POST',
headers:{'x-access-token': token},
params:{'user_id': userid},
data:{'blog_id':info}
}).success(function(data){
console.log(data);
callback(data)
})
}
I want to show glyphicon based on the value of stat
I have 6 blogs, first 3 are bookmarked and next 3 are not.
The problem i'm getting is that the stat value is always set according to the last bookmark and hence it is always false / true (based on the condition of last blog).
How to resolve this issue and set glyphicon respective to value of stat for each blog?
So there are multiple ways of implementing it.
You can either store the true/false values in either an array or you can run a function every time which returns true/false.
Using function which returns true/false values:
Modify your checkbookmark function to return true/false values as follows,
Controller code:
.controller('BlogController', function (blogFactory, $routeParams, $scope) {
this.checkbookmark = function (bId) {
blogFactory.checkBookmark(bId, function (response) {
if(response == "bookmarked"){
return true; // returns true if bookmarked
} else {
return false; // returns false if not bookmarked
}
});
};
});
HTML code:
<div class="container" ng-controller="BlogController as blogCtrl">
<div class="row" ng-repeat="chunk in blogCtrl.blogs | filter: filter_name | orderBy:'-created_at' | groupBy: 3 track by $index">
<div class="outerbox1 col-sm-4" ng-repeat="blog in chunk track by $index" >
<!-- removed ng-init here -->
<div class="innerbox3">
<br>
<div> > READ MORE
<a ng-if="blogCtrl.checkbookmark(blog._id)" ng-href="#" ng-click="blogCtrl.removebookmark(blog._id)" class="glyphicon glyphicon-heart pull-right">{{blogCtrl.stat}}</a>
<a ng-if="!blogCtrl.checkbookmark(blog._id)" ng-href="#" ng-click="blogCtrl.addbookmark(blog._id)" class="glyphicon glyphicon-heart-empty pull-right">{{blogCtrl.stat}}</a>
</div>
</div>
</div>
</div>
</div>
Using an array:
Store the true/false values in an array and access them in html using
track by $index in your ng-repeat clause.
Controller code:
.controller('BlogController', function (blogFactory, $routeParams, $scope) {
this.stat = []; // initializing array
this.checkbookmark = function (bId) {
blogFactory.checkBookmark(bId, function (response) {
if(response == "bookmarked"){
this.stat.push(true);
} else {
this.stat.push(false);
}
});
};
});
HTML code:
<div class="container" ng-controller="BlogController as blogCtrl">
<div class="row" ng-repeat="chunk in blogCtrl.blogs | filter: filter_name | orderBy:'-created_at' | groupBy: 3 track by $index">
<!-- note the usage of track by $index in ng-repeat -->
<div class="outerbox1 col-sm-4" ng-repeat="blog in chunk track by $index" >
<div class="innerbox3" ng-init="blogCtrl.checkbookmark(blog._id)">
<br>
<div> > READ MORE
<a ng-if="blogCtrl.stat[$index]" ng-href="#" ng-click="blogCtrl.removebookmark(blog._id)" class="glyphicon glyphicon-heart pull-right">{{blogCtrl.stat}}</a>
<a ng-if="!blogCtrl.stat[$index]" ng-href="#" ng-click="blogCtrl.addbookmark(blog._id)" class="glyphicon glyphicon-heart-empty pull-right">{{blogCtrl.stat}}</a>
</div>
</div>
</div>
</div>
</div>
Hope this solves the problem.
I exactly don't know which implementation is better or any other implementations for the same. May be other folks in stackoverflow could suggest.

Unable to add value in string array in angularjs?

I'm trying to add value in students array, but below code isn't working.
js code is --
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.students=[
'Scarlett Johansson','Jennifer Lawrence','Emma Stone','Kristen Stewart'
];
$scope.add = function(name){
$scope.students.push(name);
};
}]);
html code is --
<body ng-app="formExample">
<div ng-controller="ExampleController">
<p ng-repeat="stud in students">
{{stud}}
</p>
</div>
<input type='text' ng-model="name"/>
<button ng-click="add(name);">add</button>
</body>
Your button and input are not included within the div ng-controller="ExampleController" scope.
<body ng-app="formExample">
<div ng-controller="ExampleController">
<p ng-repeat="stud in students">
{{stud}}
</p>
<input type='text' ng-model="name"/>
<button ng-click="add(name);">add</button>
</div> <!-- close div here -->
</body>
You need to push into $scope.students array, as there is no students array defined in the scope:
$scope.add = function(name) {
$scope.students.push(name);
};
$scope.add = function(name) {
$scope.students.push(name);//
};

How to keep entered data of page1 after navigating back from page2 in AngularJS

I have three pages with routing. If I entered some input and getting some result on first page, next I navigated to second page and finally I came back from second page to first page. Then I want to see the data what I entered previously and result also.
Here the code snippet
index.html
<!DOCTYPE html>
<html ng-app="scotchApp">
<head>
<script src="angular.min.js"></script>
<script src="angular-route.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="mainController">
<nav class="navbar navbar-default">
<div class="container"></div>
<ul class="nav navbar-nav navbar-right">
<li><i class="fa fa-home"></i> Home</li>
<li><i class="fa fa-shield"></i> About</li>
<li><i class="fa fa-comment"></i> Contact</li>
</ul>
</div>
</nav>
<div id="main">
<div ng-view></div>
</div>
</body>
</html>
home.html
<div class="jumbotron text-center">
<h1>Home Page</h1>
Billing index :
<input type="text" ng-model='billingMapValue'>
<br/><br/>
Billing value :
{{billingMap[billingMapValue]}}
<ng-click=navigate() type="button" value='submit'>
<p>{{ message }}</p>
</div>
about.html
<div class="jumbotron text-center">
<h1>About Page</h1>
<p>{{ message }}</p>
</div>
script.js
var scotchApp = angular.module('scotchApp', [ 'ngRoute' ]);
scotchApp.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'home.html',
controller : 'mainController'
})
.when('/about', {
templateUrl : 'about.html',
controller : 'mainController'
})
.when('/contact', {
templateUrl : 'contact.html',
controller : 'mainController'
});
});
scotchApp.controller('mainController', function($scope) {
$scope.message = 'Everyone come and see how good I look!';
$scope.billingMapValue = "";
$scope.billingMap = new Array();
$scope.billingMap["ZF2"] = "Invoice";
$scope.billingMap["ZRE"] = "Credit for Returns";
$scope.billingMap["ZG2"] = "Credit Memo";
$scope.billingMap["ZL2"] = "Debit Memo";
$scope.billingMap["ZS2"] = "Cancellation of Credit Memo";
$scope.billingMap["ZS1"] = "Cancel. Invoice (S1)";
});
Now what I need is. If I run index.html page, I will be in home page there is one input text box. If enter some index value like 'ZF2' I will see the value "invoice". there will be list of hyperlinks on top of page .home, .about and .contact. I will click about item then I navigate to about page. Then I navigate again to home page by clicking home hyperlink , now I need to see the previous data which I entered and got.How to do that?
Thanks in advance.
I'd suggest you to use service, that will act as sharable resource between the different controllers.
You need to do some changes in your code.
You need to move all the static to either service or angular constant.
Use dot rule while binding object that will udpate your binding automatically.
Assign a different controller for each view, that would be more modular approach.
Service
scotchApp.service('dataService', function() {
this.data = {}
this.data.billingMap = new Array();
this.data.billingMap["ZF2"] = "Invoice";
this.data.billingMap["ZRE"] = "Credit for Returns";
this.data.billingMap["ZG2"] = "Credit Memo";
this.data.billingMap["ZL2"] = "Debit Memo";
this.data.billingMap["ZS2"] = "Cancellation of Credit Memo";
this.data.billingMap["ZS1"] = "Cancel. Invoice (S1)";
this.data.selectedBillMap = '';
});
Controller
scotchApp.controller('mainController', function($scope, dataService) {
$scope.message = 'Everyone come and see how good I look!';
$scope.billingData = dataService.data.billingMap;
});
Demo Plunkr

How do I update the model on click only (angular-strap typeahead and json)

I'm having trouble figuring out how to have dynamic data only update when the user selects from the typeahead menu or clicks the search button.
Right now, the dynamic content pertaining to the search query updates automatically when the input value is changed (content disappears). I want the content to stay in view until a new selection has been either clicked in the typeahead list or clicked by the search button.
Any insight at all would be greatly appreciated! Thank you!
Plunker demo:
http://plnkr.co/edit/jVmHwIwJ0KOKCnX6QjVa?p=preview
Code:
<!-- HTML -->
<body ng-controller="MainController">
<!-- Search -->
<div class="well">
<p>Search the term "content"</p>
<form role="form">
<div class="form-group clearfix search">
<input type="text" ng-model="selectedContent" ng-options="query as query.searchQuery for query in searchData" bs-typeahead="bs-typeahead" class="form-control search-field"/>
<button type="button" class="btn btn-primary search-btn"><span class="glyphicon glyphicon-search"></span></button>
</div>
</form>
</div>
<!-- Dynamic Content -->
<div class="well">
<h4>{{ selectedContent.contentTitle }}</h4>
<ul>
<li ng-repeat="item in selectedContent.headlines">{{item.headline}}</li>
</ul>
</div>
<!-- typeahead template -->
<ul class="typeahead dropdown-menu" tabindex="-1" ng-show="$isVisible()" role="select">
<li role="presentation" ng-repeat="match in $matches" ng-class="{active: $index == $activeIndex}">
</li>
<!-- JS -->
var app = angular.module('demoApp', ['ngAnimate', 'ngSanitize', 'mgcrea.ngStrap'])
.config(function ($typeaheadProvider) {
angular.extend($typeaheadProvider.defaults, {
template: 'ngstrapTypeahead.html',
container: 'body'
});
});
function MainController($scope, $templateCache, $http) {
$scope.selectedContent = '';
$http.get('searchData.json').then(function(response){
$scope.searchData = response.data;
return $scope.searchData;
});
};
You could use a directive such as this:
app.directive('mySearch', function(){
return {
restrict: 'A',
require: 'ngModel',
link: function($scope, $element, $attrs, ngModel){
ngModel.$render = function(){
if (angular.isObject($scope.selectedContent)) {
$scope.clickedContent = $scope.selectedContent;
}
}
$scope.updateModel = function() {
$scope.clickedContent = $scope.selectedContent;
}
}
}
})
plunker
Edit:
I added using the ngModelController. The function you set ngModel.$render to gets called whenever the model updates. If you click the typahead popup, then the model selectedContent will be an object, otherwise it'll be a string. If it's an object (meaning the user clicked the typahead popup) we do the same as we did in the updateModel function.