What to use exactly to navigate data between views/controllers in ionic - angularjs

I've started developing a simple application :
in the first view I'm retreiving all the games, and the other view i'm retreivig the game details according to the game id.
I didn't link the two pages yet.
this is what i'm facing as problem. i'm confused ! should I use ion-view ?? or I should use a normal page
for each view I have a controller which look almost like :
.controller('tomorrowmatches', function($scope, $http) {
$http.get("http://www.myappbackend/ofc/matches?date=2015-05-03")
.success(function (response) {
$scope.matches = response;
}
});
})
and how to pass data from conroller to another, in my example I wanna pass the game.id as shwon on the screenshot.
if you need more details just let me know. I just need someone to make things clear for me, and if there is an example it would be fantastic.

To pass data to another view you can use the $state and $stateParams services.
Example
Controller 1 (sends the data)
.controller('MyCtrl1', function($scope, $state) {
$scope.selectedData = function(selectedId) {
$state.go('yourState', { id: selectedId });
};
})
Controller 2 (gets the data)
.controller('YourCtrl', function($scope, $state, $stateParams) {
if ($stateParams.id) {
$scope.yourParam = $stateParams.id;
}
// Do anything you want with the ID inside $scope.yourParam
})
app.js
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('init', {
url: "/init",
templateUrl: "templates/init.html",
controller: "MyCtrl1"
})
.state('yourState', {
url: "/yourState?id",
templateUrl: "templates/your-template.html",
controller: "YourCtrl"
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/init');
})
As you can see in the state yourState I assigned an id as a parameter. This parameter will be checked if exists by YourCtrl, if it exists assign to scope and then do whatever you want with it.
Remember to set the parameter options in your app.js route configuration.
Check the ui-router docs for more info on this. You have more ways to send data.

First of all you need the ion view as a container for your views/templates..
<body ng-app="myapp">
<ion-nav-view></ion-nav-view>
</body>
then on your app.js you need to configure your routing..
// Ionic Starter App
angular.module('myapp', ['ionic', 'myapp.controllers', 'myapp.services', 'myapp.directives'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
// $httpProvider.defaults.useXDomain = true;
$stateProvider
//Page1
.state('page1', {
url: "/page1",
templateUrl: "templates/page1.html",
controller: "Page1Controller"
})
//Page2
.state('page2', {
url: "/page2",
templateUrl: "templates/page2.html",
controller: "Page2Controller",
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/page1');
});
Note: Make sure that all dependencies for ionic are included on your folder and called on your index.html..
Hope this helps :)

Related

How can I check the AngularJS controller from within the template?

I'm using Angular's UI-Router as shown below to do URL-routing in my web-app as shown below:
$stateProvider.state('myState1', {
url: '/state1',
templateUrl: 'state1.html',
controller: 'MyState1Ctrl'
});
$stateProvider.state('myState2', {
url: '/state2',
templateUrl: 'state2.html',
controller: 'MyState2Ctrl'
});
Within each of the two template files state1.html, state2.html, I have my navigation bar directive: <myapp-navigation-bar></myapp-navigation-bar>
But I want the navigation bar to behave differently based on weather it is in myState1 or myState2. How can I detect from within the controller of the navigation bar (or its template) which state it is in?
According to the documentation, You can do this,
.controller('MyState1Ctrl', function($scope, $state) {
$scope.statecurrent = $state.current;
});
You can also check like this -
.controller('MyState1Ctrl', function($scope, $state) {
if ($state.is("myState1")) {
//Add Logic
}
});

Angular ui-router shows old stale data after transition back to state

We have an ASP.NET MVC 5 application which uses ui-router AngularJS module.
When we go back to a state that has already been loaded, it always shows the old data until we do a full page refresh.
For example:
User clicks 'View Profile', we show the "ViewProfile" state, a page displaying the profile
User clicks "Edit Profile", we show the "EditProfile" state, a page with fields to edit the profile
User makes changes and clicks 'Save', they are then moved back to the "ViewProfile" state
When "ViewProfile" state loads, it still shows the old data before the edits
How can we force ui-route to pull fresh data any time it loads any state?
Angular config
var app = angular.module("MyApp", ['ngIdle', 'ui.router'])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider) {
// Configure client-side routing
$locationProvider.hashPrefix("!").html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('Home', {
url: '/',
views: {
"mainContainer": {
templateUrl: function (params) { return 'Home/Index'; }
}
}
})
.state('ProfileManagement', {
url: '/ProfileManagement-{action}',
views: {
"mainContainer": {
templateUrl: function (params) { return 'ProfileManagement/' + params.action; }
}
}
})
}]);
How we are doing the transition
$state.go(stateName, { action: actionName }, { reload: true, inherit: false, notify: true });
EDIT w/ Solution
Since all the functionality is written using jQuery, we cannot use Angular controllers to control the data. Our solution was to completely disable Angular template caching with the following code:
app.run(function ($rootScope, $templateCache) {
$rootScope.$on('$viewContentLoaded', function () {
$templateCache.removeAll();
});
});
By default ui-router state transition will not re-instantiate toState's controller.
To force instantiation of the controller, you can do this.
//assuming you are using $state.go to go back to previous state
$state.go('to.state', params, {
reload: true
});
You need to use resolves, like so:
var app = angular.module("MyApp", ['ngIdle', 'ui.router'])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider) {
// Configure client-side routing
$locationProvider.hashPrefix("!").html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('Home', {
url: '/',
views: {
"mainContainer": {
templateUrl: function (params) { return 'Home/Index'; }
}
},
resolve: {
loadedData: (injectable) => injectable.getData()
}
})
.state('ProfileManagement', {
url: '/ProfileManagement-{action}',
views: {
"mainContainer": {
templateUrl: function (params) { return 'ProfileManagement/' + params.action; }
}
},
resolve: {
loadedData: (injectable) => injectable.getData()
}
})
}]);
In each state, there is a resolve, calling the method 'getData()' in the injectable service (I'm saying a 'service' because that's where we would have the data loaded from).
Then for each state's controller, it will have access to the loadedData resolve; the data will already be loaded at that point and be usable by that controller. So for your case scenario, going back to the state you've come from, the newly updated data will be loaded again and available in that state again.
Keep your state transition the same, with the reload: true, as that is what you want as well.
Maybe this work for your problem.
In your angular main page you should have something like this:
app.run(['$rootScope', function ($rootScope){
$rootScope.$on('$stateChangeStart', function(event, toState){
$rootScope.UrlActive=toState.name;
});
}]);
In your angular controller you should have something like this:
app.controller('AnalisisCtrl', ['$scope','$rootScope', function ($scope,$rootScope) {
$scope.$watch('UrlActive', function(newValue) {
if(newValue="ProfileManagement"){
doSomething();
};
});
}]);

ui.router not being loaded/executed

I am new to ui.router and trying to get it working on a new application. The code is behaving like the state provider is either not loaded or it does not see the ui-view DOM element. I know the dependency is loaded properly (or least it isn't throwing any errors) and I have been over a ton of blog posts but everything looks right. I have a couple 'made it here' style messages but I never see them in the console.
The plunk below shows the following paragraph is not an issue. I am leaving the paragraph here for posterity but do not see a strike-through option in SO formatting...
I should also point out that this will be a SharePoint provider hosted app so there is a ton of query string garbage that I suspect is mucking things up. Unfortunately I can't get rid of them.
---Edit---
I made a plunk
/---Edit---
Here is my module:
var app = angular.module('myApp', ['ui.router']).
config(['$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: '/',
templateUrl: 'partials/admin.html',
onEnter: function ($stateParams) {
console.log("Entered Admin route");
}
//controller: 'myController'
})
.state('sitebinding', {
url: '/sitebinding',
templateUrl: 'sitebinding.html'
})
.state('scrum', {
url: '/scrum',
templateUrl: 'scrum.html'
});
$urlRouterProvider.otherwise('/');
}
]);
angular.module('myApp',[
'myApp.controllers'
]);
Here is the controller:
angular.module('myApp.controllers', []).
controller('myController', function ($scope) {
$scope.models = {
helloAngular: 'I work!'
};
$scope.$on('$stateChangeStart', function (evt, toState, toParams, fromState, fromParams) {
console.log('In state change start');
})
});
And here is the relevant bits from the index.cshtml.
<div data-ng-app="myApp">
<div>
<div class="container">
<div ui-view="app"></div>
</div>
</div>
</div>
Not sure what your trying to do here in your plunkr. You have scrum.html in your route setup but it does not exist in your file tree. Are you just trying to get admin.html to show? Are you trying to fire this view on a click?

Angular - Wait $http finish until go to the next line

It's a simple webshop. So I'd like to load several things before show the home page and the controller.
I decided that the index.html will be also the Master Page containing a header, the ui-view for routing templates , a sidebar containing the categories and a footer.
<body ng-app="app">
<header ng-include="'./templates/masterPage/header.html'"></header>
<div ui-view></div>
<sidebar ng-include="'./templates/masterPage/sideBar.html'"></sidebar>
<footer ng-include="'./templates/masterPage/footer.html'"></footer>
</body>
The things on header, sidebar and footer will came from a json file containgin everything I need such as categories, currency, name of the webshop and others things that's will never changes after load.
So, I created the following app.js...
angular
.module('app', [
'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider',
function ($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'templates/common/home.html',
controller: 'homeCtrl',
})
}])
.run(function ($rootScope, $http) {
$rootScope.api = "http://127.0.0.1:5000/demoShop";
var call = $rootScope.api + "/frontEnd/loadStructure";
$rootScope.webshop = $http.get(call).then(function (response) {
console.log('1');
return response.data;
});
console.log("2");
})
The problem is: check the console.logs in the end....2 executes before 1 because I can't make the $http to wait until go to the next line. How can I do it ?
I need to populate the webshop variable on rootscope before do anything.
Simple answer:
You can't.
Longer answer:
You can wait for the AJAX request to finish. That's what you're already doing - it's the function in .then. You can put your code there. Question is - why do you need it to be finished first? Or maybe better question is why do you need to do the request in the controller? Isn't it a bit too late for that? See related answer from Misko Hevery.
I would suggest resolving the data when the homeCtrl for the root-route loads. Then you can access you webshop data apon instaciation of the controller. Consider the example below:
angular
.module('app', [
'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider',
function ($urlRouterProvider, $stateProvider) {
var resolveLoadStructure = function() {
$rootScope.api = "http://127.0.0.1:5000/demoShop";
var call = $rootScope.api + "/frontEnd/loadStructure";
return $http.get(call);
};
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'templates/common/home.html',
controller: 'homeCtrl',
resolve: {
loadStructure: resolveLoadStructure
}
});
}])
.controller('homeCtrl', function($scope, loadStructure) {
$scope.webshop = loadStructure;
})
I found the problem. My mistaken is to set the $rootScope directly - Instead I set this inner the callback. I just made a small surgery and everything works fine. Take a look
.run(function ($rootScope, $http) {
$rootScope.nodeshop = "http://127.0.0.1:5000/rawDemo";
var call = $rootScope.nodeshop + "/frontEnd/loadStructure";
var head = {};
$http.get(call).then(function (response) {
$rootScope.webshop = response.data; //See ? this variable is no longer set as result of the $http return !
return response.data;
});
})

Routing Angular UI Router

I'm using Angular UI Router and I'm having trouble defining my routes.
I have some basic routes with states and URLs registered:
/about,
/register,
/ (Startpage).
When the user registers I want to give them a dynamic URL to their own personal page.
And this would be a paramaterized state.
I would like the URL to be http://www.whatever.com/[username]
and if the user does not exist, redirect to a 404.
However, If i register a state named '/{userName}' this conflicts with my other routes
and takes over all requests. How do I let through all statically registered routes?
I could do http://www.whatever.com/profile/[username]. But that's not what I, nor the client I'm developing for, wants.
Maybe I could use regexp to let the statically registered routes plus the base route '/'?
Maybe there is another great solution out there!
You can fix this by defining the wildcard route after the static routes.
Here's a plunker: http://plnkr.co/edit/4pBWkhq4FDhLWqdCfkES?p=preview
var app = angular.module('plunker', ['ui.bootstrap', 'ui.bootstrap.tpls', 'ui.router'])
.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}]);
app.config(function($stateProvider,$locationProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/about");
$stateProvider
.state('about', {
url: "/about",
views: {
"viewA": {
template: 'About'
}
}
})
.state('register', {
url: "/register",
views: {
"viewA": {
template: "Register"
}
}
})
.state('dynamic', {
url: '/{val}',
views: {
"viewA": {
template: "Dynamic route"
}
}
});
});
I've solved the problem.
It was all about the order of execution.
All my routes is being registered in the seperate config-block in their respective module.
and the config block with the '/' i.e. starroute had the wrong module-name. it was being registered into the 'app'-module when it was supposed to be registered into the 'app-startPage'-module. In that way it was always registered last, when it's supposed to be registered first!
Thanks anyway and hurray for copy-paste-mistakes!

Resources