I have a page in my AngularJS that has an edit button, I need to open the edit page on another tab when I click the edit button. Can it be possible using the angular way? I need to use the same controller to be able to access the data. How can I possible do this? Can someone please give me a sample?
Here's a fiddle to show opening the tab:
https://jsfiddle.net/e8g1m0xs/
I.e.:
angular.module('new_tab', [])
.controller('ExampleController', ['$scope', '$window', function($scope, $window) {
$scope.openTab = function() {
$window.open('https://www.google.com', '_blank');
};
}]);
<div ng-app="new_tab" ng-controller="ExampleController">
<button ng-click="openTab()">New Tab</button>
</div>
But in order to use the same controller for the new tab, and do something like pass information to it, you would have to implement a wildcard pattern into your angular router to pass along state information. I usually do things like that using UI Router. See the section titled URL Parameters.
Related
I'm totally new to Ionic and JavaScript and I'm having a few problems when changing views in my project.
I've created the project using the tabs starter, and everything works when moving withing the default tabs and even when adding new ones. At certain parts of the code, I need to move to a tab view so I'm using the $state.go() function and it works fine. However, I've added a new view with its template, controller, and state and I need to load it when clicking a button. So I use $state.go() again, but the URL in the explorer changes but not the view, it stays in the previous one. It doesn't work either when I type the URL in the browser, so maybe the problem is in the state definition, but I'm pretty sure it is ok.
State
.state('tab.file_explorer', {
url: '/file_explorer',
views: {
'tab-file_explorer': {
templateUrl: 'templates/tab-file_explorer.html',
controller: 'file_explorerCtrl'
}
}
})
Controller
It is in the controller of another view where the button is located (the button works fine, I've tested it). The file_explorerCtrl controller is empty at the moment.
.controller('load_csvCtrl', function($scope, $state) {
$scope.loadCsv = function(){
$state.go('tab.file_explorer');
}
}
This redirects to the URL http://localhost:8100/#/tab/file_explorer, with no console output or 404 errors. I've also tried using $location.path() and $window.location.assign() but it also fails to load the template.
I'd appreciate any help.
Can you check if your index.html has <ion-nav-view></ion-nav-view> tag
You're using named views. your <ion-nav-view> should match the name:
<ion-nav-view name="tab-file_explorer"></ion-nav-view>
Check the docs here:
https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
Set cache-view="false" in View.
Example:
<ion-view cache-view="false">
<!-- View Content goes here -->
</ion-view>
I have an app I've written that takes a name as an argument, but when I click the link after loading some other name the page does nothing, despite the new arguments passed via the URL. I'd imagine the Angular DOM isn't having it reload since it's "technically" the same webpage. I do, however, need it to load the updated data.
Here's the Angular JS/HTML that populates the list of links:
<li ng-repeat="internalRep in internalReps ">{{internalRep.such}}</li>
Now when you're on a totally different page and click one of the links it works perfectly. However, if you're already on ./repweekly.html#!?rep=REP1 and click on the link to go to ./repweekly.html#!?rep=REP5 it'll change the URL in the URL bar, but nothing else happens. If you then click the refresh button the correct data loads.
I changed the code to this:
<li ng-repeat="internalRep in internalReps "><a ng-href="./repweekly.html#!?rep={{internalRep.such}}">{{internalRep.such}}</a>
and again, while the URL in the address bar changes, the page doesn't reload to show the updated rep.
Alrighty, here's what I ended up doing -
The link stays as Josué suggested with one exception - I added an ng-click directive ( ng-click="reloadRep()" ) to it:
<li ng-repeat="internalRep in internalReps"><a ng-href="repweekly.html#?rep={{internalRep.such}}" ng-click="reloadRep()">{{internalRep.such}}</a></li>
I then injected $window into the controller:
angularApp.controller('mainController', ["$scope", "$http", "$filter", "$location", "$window", function ($scope, $http, $filter, $location, $window) {...
and finally I created the function that runs when ng-click is called:
$scope.reloadRep = function () {
$window.location.reload();
};
I have started building a website using Angular, and have started to use ui-router along with ngAnimation for some sick animations! All was going well until I started adding external resources such as Facebook's Page Widget (https://developers.facebook.com/docs/plugins/page-plugin) and Google Maps API for some custom map styles.
The Issue
I have the Facebook widget on the home page, and it loads fine when you first access the URL as can be seen below (Have to block the name of client, totally not just bad design...):
Once I click on another page to load it in (using ui-view to dynamically bring in a view), for example contact view and go back to the home page (where the code is to display the widget), the widget will no longer load but will load the basic header tag that Facebook provide as can be seen below:
This also happens on the contact page when loading in Google Maps API. If I click on the contact page, there will just be a large white area on where the map should be, but if you had to actually refresh the page the map will load.
I am assuming that the issue is that the website is not able to send a request to either Facebook or Google when a view is loaded in, but can only happen when the page is actually refreshed or a new page load.
My Code
Okay so I'll explain the basics of how my application works along with code. I am rather new with Angular so if I have terrible code, please let me know.
Structure
This is a screen shot of my web apps structure. The main template file is index.html, and any view are within the views directory, which are loaded in using ui-router.
Main Angular applications code (app.js)
var app = angular.module('bmApp', ['ngAnimate', 'ui.router', 'ui.bootstrap'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('header', {
templateUrl: './assets/views/template.html',
})
.state('header.home', {
url: '/',
templateUrl: './assets/views/home.html',
controller: "HomeController"
})
.state('header.about', {
url: '/about',
templateUrl: './assets/views/about.html',
controller: "AboutController"
})
.state('header.work', {
url: '/work',
templateUrl: './assets/views/work.html',
controller: "WorkController"
})
.state('header.services', {
url: '/services',
templateUrl: './assets/views/services.html',
controller: "ServicesController"
})
.state('header.contact', {
url: '/contact',
templateUrl: './assets/views/contact.html',
controller: "ContactController"
});
$urlRouterProvider.otherwise('/'); //if no views are matched, just redirect back to home page.
})
I am using nested views to keep the header of the website static (not changing) and then loading in views under the header, with ngAnimate to make it look cool.
In my main template, index.html, I have a simple <div ui-view></div> to load in the view that is requested. I also have the required script to request Facebook's API just after the . My controllers do not actually currently have anything in them. I did have some vanilla JavaScript in some, but do not currently need it anymore. I also tried to wrap the code provided by Facebook in a function, and call it within the controller for the specific view but that just had the same results of having it within the body on the template (index.html) page.
Pulling my hair out at this, can't seem to find a solution. I hope I have explained my issue without missing out on anything. I appreciate any help you could give, would be so awesome.
Edit: I should have probably mentioned that my main template is index.html, I then inject the view in to /views/template.html AND THEN inject it into index.html. Not too sure if this is best practice, but felt like it would work well (I don't think that is the issue).
I will give you only half of an answer, but maybe it will point you to right direction. I also struggled with Google API in SPA application once. I had the same issue - after entering the contact page, a white box appeared instead of map. The solution turned out to be simple - I just needed to force map reload, when I entered contact sheet. This function was attached as onclick event to contact page link:
function reloadGoogleMap() {
if (counter == 0) {
document.getElementById('google-map').src += '';
counter++;
}
}
I used the counter to make sure it happens only once - you won't need it probably. With Angular, you might need to make sure the reload happens after element is rendered. Maybe a simple directive would work, however I didn't test that:
angular.module('your_directives_module')
.directive('mapLoaded', [mapLoadedDirective]);
function mapLoadedDirective() {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
elem.on('load', function (event) {
// Force reload
elem.src += '';
});
}
};
}
It could be used like:
<!-- Div/iframe with google map -->
<div map-loaded></div>
Maybe Facebook API also has some simple way which you could use to force widget reload when the partial view is loaded, however I've never tried to use that with Angular.
Don't you have to wrap it in a $rootScope.$apply function in order to update your view?
$rootScope.$apply(function () {
// some code
});
I have a PhoneGap app, that has multiple html pages.
I use one controller, called AppController, that loads the data for the startup screen and default pages.
I added a new page to the navigation bar, which, when clicked & opened should load up data from the server with a php call, so it should only make a php call, when the page is shown.
This page uses the same controller as the rest of the app.
I am really new to AngularJS, so I might've programmed it in a bad way, but the rest of the data for the home page is loaded in the appController like this
myApp.controller('AppController', function ($scope, $timeout, sharedProperties) {
$scope.items= {};
$scope.items[item1] = {....} //LOADING UP the items collection
}
How can I hook up an "onload" event or something, that would only fire when the page is shown?
There are so many ways you could do that, one of them:
// inside your controller
angular.element(document).ready(function () {
// your code
});
another one:
<div ng-controller="myCtrl" ng-init="someinitfunc()"></div>
How about using ng-init() directive on your next page ?
I just got a request from our QA team, which I think sounds ridiculous. Here it goes: suppose you are already on the 'about' state/page in the angular-based app, and when you click on the 'about' state url again from the top menu, you want the 'about' page to reload. The about page does not fetch data from anywhere, by the way, a reload is simply equivalent to a blink.
For the state config in my angular app is like this:
.state('about', {
url: '/about',
templateUrl: '/path/to/about.html',
controller: 'aboutCtrl as aboutView'
});
And in the top menus, we have a link pointing to this state:
<a ui-sref="about">About</a>
I have tried many things to get this to work: clicking the link triggers the reload of the same state.
Things like $state.go('about', {}, {reload: true}); or $state.transitionTo('about', {}, {reload: true}); don't work, because the links are static.
One last resort I am currently trying is to manipulate the reload thing in the run phase of Angular by listening to '$stateChangeSuccess' event, but I don't think it will work, because there's no state change at all if you click on the 'about' link while you are right on that state.
Is there any ways to work around this? Thanks
There is an option attribute called ui-sref-opts that comes with the UI Router. I faced the same problem and it solved it.
Eg: <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
Docs URL : UI Router DOcs
You're right, I can't get any state change events to fire either once already in that state. Until, and if that functionality becomes available to use through that api someday, here's a semi-hacky solution for this. We can just leverage ng-click and use some silly logic to appease QA (in your case). Also, I don't know your controller implementation, so I placed my suggestion on $rootScope in .run in this example for simplicity and visibility, but integrate accordingly if you choose to do so. Observe the following example...
<a ui-sref="about" ng-click="sillyQA()">About</a>
.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.sillyQA = function() {
if($state.current.name === 'about') {
$state.go('about', {}, { reload: true });
}
}
// -- just to see our about => about state 'change'
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
console.log('toState: ' + toState.name );
console.log('fromState: ' + (fromState.name || 'Just got there! click again!'));
})
}]);
JSFiddle Link - demo