How to refresh the previous page using AngularJS? - angularjs

We have ASP.NET application where we use AngularJS. There's a page with the table (list) that contains pictures and their properties. The pictures are in first column of the table. The code looks as following:
<td>
<a ng-href="{{pic.FullUrl}}" target="_blank">
<img class="img-thumbnail" ng-src="{{pic.FullUrl}}" alt="{{pic.AltText}}" />
</a>
</td>
We can edit some picture by clicking "Edit" button and go to the next page (edit). After we made the changes, we click "Back" button to return to the previous page (list).
The issue is the image on first page hasn't been refreshed if we changed it on edit page, that is pic.FullUrl doesn't take effect.
I've tried to use the watch function, but no luck.
How to make it work?
UPDATE
We have a service:
PictureApp.factory('PictureService', function ($http, $location) {
var PictureService = function () {
this.ToList = function (objType, objId, mode) {
$location.path('/' + objType + '/' + objId + '/' + mode);
};
And we use it when accept changes on edit page in this way:
$scope.Accept = function () {
...
query.then(function () {
PictureService.ToList($routeParams.objType, $routeParams.objId, $routeParams.mode);
});
};
As you can see we call ToList and go to list page, but without reloading.
In list's controller we have this:
$scope.$watch('rbMode', function (val) {
PictureService.ToList($routeParams.objType, $routeParams.objId, val);
});
On list page we have this:
<div ng-if="dataLoaded">
<div ng-switch="rbMode">
<div ng-switch-when="static">
<div ng-include="'partials/Pic/PicTable.htm'" onload="this.pics = data;"></div>
</div>
<div ng-switch-when="banner">
<accordion close-others="false">
<accordion-group is-open="expandBanners" heading="{{pics[0].TypeDescription}}" ng-repeat="pics in data">
<div ng-include="'partials/Pic/PicTable.htm'" onload="this.pics = $parent.pics;" ></div>
</accordion-group>
</accordion>
</div>
</div>
</div>
And PicTable.htm looks as following:
<tr ng-repeat="pic in pics" ng-class="{'movable-row':isBanner}">
<td>{{pic.PictureLinkID}}</td>
<td>
<a ng-href="{{pic.FullUrl}}" target="_blank">
<img class="img-thumbnail" ng-src="{{pic.FullUrl}}" alt="{{pic.AltText}}" tooltip-popup-delay='1000' tooltip-placement="right" tooltip="Кликните, чтобы открыть в полном размере" />
</a>
</td>

Sounds like you have an image cache issue. Place a timestamp parameter on the end of your image url "*.jpg?ts=3324324". This will let the browser know it needs to refetch the image once it has been edited. Initialize the timestamp when the page loads and update the timestamp whenever an image is edited.
You can try the plnkr below which you can observe in your network panel, will fetch the image each time the timestamp is updated.
Edit: updated to demonstrate communication across controllers.
http://plnkr.co/edit/lp9lwkR3hgsqtIt4c3N0?p=preview
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.4.0-rc.1" src="https://code.angularjs.org/1.4.0-rc.1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div ng-controller="cntrl">
<img ng-src="{{imgurl}}'?ts={{lastEdit}}" />
</div>
<div ng-controller="editCntrl">
<button ng-click="updateTS()">Update ts</button>
</div>
<script>
var app = angular.module("app",[]);
app.controller("cntrl",function($scope){
$scope.lastEdit = (new Date()).getTime();
$scope.imgurl = "http://dummyimage.com/600x400/000/fff";
$scope.$on("edited",function(){
$scope.lastEdit = (new Date()).getTime();
});
});
app.controller("editCntrl",function($scope,$rootScope){
$scope.updateTS = function(){
$rootScope.$broadcast("edited");
}
});
angular.bootstrap(document,["app"]);
</script>
</body>
</html>

You can add time stamp to uniquely identify image url on change.
on edit add the time stamp like this...
pic.FullUrl = "...path/pic.jpg"+ "?ts=" +new Date();
this will tell the browser that your image had been changed and it will do refresh.

Related

How to navigate from tab to different Page and viceversa in angularJS?

If i am having One page with 2 tabs. and if from 2nd tab i am navigating to different page. then how to come back to that 2nd tab from navigated page? i am using $StateProvider.
Thanks.
Here is the example code and it works well,
index.html
----------------
<html>
<head>
<title>Tabs Directive</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-rc.0/angular.min.js"></script>
<script src="tabController.js"></script>
</head>
<body>
<div class="container">
<section ng-app="myApp" ng-controller="TabController as tab">
<ul class="nav nav-pills">
<li ng-class="{active:tab.isSet(1)}"><a href ng-click="tab.setTab(1)">Tab 1</a></li>
<li ng-class="{active:tab.isSet(2)}"><a href ng-click="tab.setTab(2)">Tab 2</a></li>
<li ng-class="{active:tab.isSet(3)}"><a href ng-click="tab.setTab(3)">Tab 3</a></li>
</ul>
<div ng-show="tab.isSet(1)">
<h4>Tab 1</h4>
</div>
<div ng-show="tab.isSet(2)">
<h4>Tab 2</h4>
</div>
<div ng-show="tab.isSet(3)">
<h4>Tab 3</h4>
</div>
</section>
</div>
</body>
</html>
tabController.js
----------------
var app = angular.module('myApp', []);
app.controller('TabController', function () {
this.tab = 1;
this.setTab = function (tabId) {
this.tab = tabId;
};
this.isSet = function (tabId) {
return this.tab === tabId;
};
});
Thanks Atul :)
but this solution worked for me.
we can have one flag varibale ilke "this.isPageVisited=false" in APPCONTEXT.js file. so that variable will be available throughout the project. so suppose from tab of one page i am going to different page, what i do is i set isPageVisited=true via setter method in visted page . so now to come back to tab page again, we check the variable if its true or not. if it is true we put the "active" class to the tab element.
so that the we can have current tab active from where navigation started.

I can't get the response from BreweryDB API to show in my simple app

I am working with the BreweryDB API and I can't even get the response to show in my simple app.
Here is the app.js file that houses the controller. I am simply using a HTTP GET to load the API data.
angular.module('BreweryGuideApp', [])
.controller('BreweryGuideController', function($scope, $http){
var pendingTask;
if($scope.search === undefined){
$scope.search = "300 Suns Brewing"; // init search bar data
fetch(); // call fetch function
}
$scope.change = function(){
if(pendingTask){
clearTimeout(pendingTask);
}
pendingTask = setTimeout(fetch, 800);
};
function fetch(){
$http.get("https://api.brewerydb.com/v2/brewery/x4vqAl?key=cc12540abedfa669021307d4ba111d87&format=json")
.success(function(response){ $scope.details = response.data; }); //get API response on success
} //end fetch
}); // end controller
Here is the HTML file:
<!DOCTYPE html>
<html>
<head>
<title ng-bind="'Brewery.Guide - ' + data.name"></title>
<link rel="stylesheet" href="css/animate.min.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/bootstrap.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
</head>
<body ng-app="BreweryGuideApp" ng-controller="BreweryGuideController">
<div class="container-fluid outerdiv">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#"><b>Brewery.Guide</b> <span class="span-style">Get Yer Drink On</span></a>
</div>
</div>
</nav>
<noscript>
<div class="nojs">Javascript is either disabled or not supported in your browser. Please enable it or use a Javascript enabled browser.</div>
</noscript>
<div class="animated zoomInRight">
<div class="input-group search-bar">
<input type="text" ng-model="search" ng-change="change()" onclick="select()" class="form-control" placeholder="Enter brewery name" autofocus />
<span class="input-group-addon bar-style"><i class="glyphicon glyphicon-search"></i></span>
</div>
<div id="main-info" ng-include="'partials/main-info.html'" class="col-md-8"></div>
<div id="related-results" ng-include="'partials/related-results.html'" class="col-md-4 animated bounce related-results"></div>
</div>
</div>
<script src="js/angular.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>
And this is the main-info.html to be inserted using the ng-include directive:
<div ng-if="details.status!=verified">
Loading results...
</div>
<div ng-if="data.status==verified">
<span class="span-outer">
{{ data.status }}
{{ data.name }}
</span>
</div>
Here is the data that I get from the URL I am using in app.js:
{
"message":"Request Successful",
"data":{
"id":"x4vqAl",
"name":"300 Suns Brewing",
"description":"300 Suns Brewing was really just an idea brought up years ago, that kept surfacing every time a brewery was toured, a GABF was attended, a new craft beer was tasted, a bottle of homebrew was shared on the back deck in the cool summer evening air. It was just a dream and one day (gulp), we worked up the nerve to make it a reality. We wanted to put our time and our work into something that brought joy to others the way those moments brought joy to us. And we wanted to give our community very meaningful ways that they could become part of the shaping of our brewery.",
"website":"http:\/\/www.300sunsbrewing.com",
"established":"2014",
"isOrganic":"N",
"images":{
"icon":"https:\/\/s3.amazonaws.com\/brewerydbapi\/brewery\/x4vqAl\/upload_fI8k35-icon.png",
"medium":"https:\/\/s3.amazonaws.com\/brewerydbapi\/brewery\/x4vqAl\/upload_fI8k35-medium.png",
"large":"https:\/\/s3.amazonaws.com\/brewerydbapi\/brewery\/x4vqAl\/upload_fI8k35-large.png"
},
"status":"verified",
"statusDisplay":"Verified",
"createDate":"2014-05-05 12:24:15",
"updateDate":"2015-08-14 16:49:36"
},
"status":"success"
}
Very simple, but I can't even get it to load any data. The search input field is really irrelevant, but I included it in case that might be causing an issue.
You refer details as data in HTML. However, in the controller.js, you don't have any variable like $scope.data. So that's why you cannot load the data. In order to let HTMLor template can access the variable, you can declare the variable in $scope. (using $scope dot notation) format.
Because you are using $http().success() method, it returns you the data, so you don't do $scope.details = response.data, instead, you should do $scope.details = response;
Controller.js
function fetch(){
$http.get("https://api.brewerydb.com/v2/brewery/x4vqAl?key=cc12540abedfa669021307d4ba111d87&format=json")
.success(function(data) {
$scope.details = data;
});
} //end fetch
HTML
<div ng-if="details.status!=verified">
Loading results...
</div>
<div ng-if="details.status==verified">
<span class="span-outer">
{{ details.status }}
{{ details.name }}
</span>
</div>

angular ng-click add http data inside ng-repeat

I use $http.get php data in ng-repeat is correct,but I have a problem when ng-click to add push php second page data in ng-repeat ,but it not work .
Any suggestions ? thanks.
I did not write very clear , i mean when click button , i want get ats01.php?page=2 data, add ats01.php?page=1 data in li ng-repeat, i don't want get page2 data replace page1 data,just like jquery $('#ul01').append (html) method; thank your answer it .
script.js
var scotchApp = angular.module('scotchApp');
var myurl="http://192.168.5.9/"
scotchApp.controller('mainController', function($scope, $http) {
$http.get(myurl+"php/ats01.php?page=1")
.success(function (response) {$scope.names = response.records;});
$scope.myur=myurl;
$scope.add = function() {
$http.get(myurl+"php/ats01.php?page=2")
.success(function (response) {
$scope.names.push(response.records);
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html >
<head >
<script src="anjs/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="scotchApp" >
<div ng-controller="mainController">
<ul >
<li ng-repeat="x in names track by $index">
<p > <small>{{x.TA002}} {{x.TA003}} {{x.TA004}} {{x.TA012}}</small> </p>
</li>
</ul>
<p> <button ng-click="add()">Add</button> </p>
</div>
</body>
</html>
For first time you are assigning record in the list
$scope.names = response.records;
But in click you are pushing same data instead of assigning
$scope.names.push(response.records);
If you push instead of assign it'll create a index and push whole data into that index.
Convert this
$scope.names.push(response.records);
to this
$scope.names=$scope.names.concat(response.records);

nicEdit doesn't work in templates

I'm trying to add the wysiwyg nicEdit text editor to my text areas. When I goto the actual templateUrl the textbox and tool bar do work but they do not submit correctly (to my firebase db). When I goto the page that is to render the template I am unable to get get nicEdit toolbar features and just get a regular text area box. I'm using angularjs and have the templateurl as addPost.html.
So again the template does render when I goto #/addPost but not with the working nicEdit features, yet going directly to the template url addPost.html does have the nicEdit features working but then won't submit to my firebase db. Anyone have an idea on why this is so? Thanks.
Template file addPost.html:
<head>
<script type="text/javascript" language="javascript" src="../nicEdit.js"></script>
<script type="text/javascript" language="javascript">
bkLib.onDomLoaded(nicEditors.allTextAreas);
</script>
<!-- Bootstrap core CSS -->
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<nav class="blog-nav">
<a class="blog-nav-item " href="#/welcome">Home</a>
<a class="blog-nav-item active" href="#/addPost">Add Post</a>
<a class="blog-nav-item " style="cursor:pointer;" ng-click="logout();">Logout</a>
</nav>
</head>
<body ng-controller="AddPostCtrl">
<div class="container" >
<form class="form-horizontal" ng-submit="AddPost()">
<fieldset>
<!-- Form Name -->
<legend>Create Post</legend>
<!-- Textarea -->
<div class="form-group">
<label class="col-md-4 control-label" for="txtPost">Post</label>
<div class="col-md-4">
<textarea class="form-control" id="txtPost" ng-model="article.post" name="txtPost" ></textarea>
</div>
</div>
</fieldset>
</form>
</div><!-- /.container -->
</body>
addPost.js
'use strict';
angular.module('myApp.addPost', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/addPost', {
templateUrl: 'addPost/addPost.html',
controller: 'AddPostCtrl'
});
}])
.controller('AddPostCtrl', ['$scope','$firebase','$location','CommonProp',function($scope,$firebase, $location,CommonProp) {
if(!CommonProp.getUser()){
$location.path('/main');
}
$scope.logout = function(){
CommonProp.logoutUser();
}
$scope.AddPost = function(){
var title = $scope.article.title;
var date = $scope.article.date;
var post = $scope.article.post;
var firebaseObj = new Firebase("http://..");
var fb = $firebase(firebaseObj);
fb.$push({ title: title, date: date, post: post,emailId: CommonProp.getUser() }).then(function(ref) {
console.log(ref);
$location.path('/welcome');
}, function(error) {
console.log("Error:", error);
});
}
}]);
Going to #addPost shows the template with out nicEdit working
But going to the actual templateUrl addPost.html it works fine, minus not being able to submit
The problem has to do with trying to run scripts Angular html partials. The simple solution is to move the scripts you need to the head of your main index file, outside of ng-view, though it does seem (according to other stackoverflow posts) technically possibly to try to get these scripts to execute:
"AngularJS: How to make angular load script inside ng-include?"
https://stackoverflow.com/a/19715343/1078450
(Also, you have html in your head file that is not likely to be rendered: <nav class="blog-nav">)
Well, I have had the same problem, with initialisation of NicEdit in templates.
First I used onDomLoaded() else, but it's better to wait for the document. With jQuery I use document.ready.
Take a look here, pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it
The problem is to tell NicEditor the new textarea.
Here a code sample to do this in jQuery.
var idnr = 0;
var NicEditor = new nicEditor();
$('#add').click(function(){
var $clone = $('#dummy').clone();
var id = 't_' + idnr;
idnr = idnr + 1;
$clone.attr('id',id).attr('name',id).removeClass('dummy');
$('#wrapper').append($clone);
NicEditor.panelInstance(id);
$(nicEditors.findEditor(id).elm).focus();
});
And here is a working Example of dynamic NicEdit use.

Angular - 2 dependent menus binding

I build a ASP.Net MVC 4 + angular website,
I have an upper menu, while a click on one link will open the left menu links accordingly.
suppose you click the first category (1) upper menu, the left menu will be exposed accordingly 1.1, 1.2, 1.3.
Currently, my upper menu is binded, but when clicking on a link (category), nothing happens on the left menu.
if i put alert, i see the data comes back to the client. it is not a data problem.
any idea guys ? :-)
my index.html to contain the 2 partials:
<html>
<head>
<script src="Scripts/angular.min.js"></script>
<script src="app/controllers/menuController.js"></script>
<title></title>
</head>
<body ng-app="generalApp">
<div ng-include="'partials/topMenu.html'"></div>
<div ng-include="'partials/sideMenu.html'"></div>
</body>
</html>
my upper menu (different html file - working):
<div ng-controller="menuController">
<table>
<tr ng-repeat="category in menuCategories">
<td>
<a href="#" ng-click="loadSideMenu('7')">
{{category.CategoryName}}
</a>
</td>
</tr>
</table>
</div>
my side menu (different html file):
<div ng-controller="menuController">
<table>
<tr ng-repeat="category in sideMenu">
<td>{{ category.CategoryName }}</td>
</tr>
</table>
</div>
my js controller code:
(function (angular) {
var generalApp = angular.module('generalApp', [])
.controller('menuController', function ($scope, $http) {
$http.post("Home/GetArticleCategories").then(function (response) {
$scope.menuCategories = response.data;
});
$scope.loadSideMenu = function(category) {
$http.post("Home/GetSideMenu?a="+category).then(function (response) {
$scope.sideMenu = response.data;
});
};
});
}(angular));
my mvc controller to return the faked links upon the category click :
public JsonResult GetSideMenu(int a)
{
var j = Json(new[]{
new { CategoryName = "link 1"},
new { CategoryName = "link 2"}
}
);
return j;
}
Thanks to any idea !!!
You must put upper and left menus inside the same ng-contoller. The way you did every div will have a different $scope. When you populate the data in the upper menu, the $scope from the upper menu will hold the list, and the left will not notice that, because they have different $scopes.
Think as they are the same kind of object, but different instances!

Resources