Creating Stateful Modals with Angularjs and MaterializeCSS - javascript

I am trying to utilize the Materialize Framework's Modal component along with Angularjs' ui-router module, but I'm having trouble trying to configure it properly.
Here's my $stateProvider definition
// Modal States ===============================
.state("modal", {
views:{
"modal": {
templateUrl: "resources/templates/modal.html"
}
},
abstract: true
})
.state("modal.modal1", {
views:{
"modal": {
templateUrl: "resources/templates/modals/modal-content-1.html"
}
}
})
And the `ui-view' definition on my index.html along with the trigger
<div ui-view="modal" autoscroll="false"></div>
What I'm trying to figure out is how to both render the modal and simultaneously switch to the modal1 state using the trigger on the Materialize button.
The init of the modal is simple enough:
<a class="waves-effect waves-light btn" href="#modal1">Modal</a>
<!-- Modal Structure -->
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Modal Header</h4>
<p>A bunch of text</p>
</div>
<div class="modal-footer">
Agree
</div>
</div>
Any thoughts? Thanks much!

It seems that the state config you wrote is not correct, you have used the same named "modal" ui-view in both parent and child states.
Does your resources/templates/modal.html also contains a ui-view named "modal" ?
As your parent state is abstract, it can not be activated but for any child state to render, your parent state's template should have a ui-view.
Example below:
$stateProvider
.state('contacts', {
abstract: true,
url: '/contacts',
// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
template: '<ui-view/>'
})
.state('contacts.list', {
// url will become '/contacts/list'
url: '/list'
//...more
})
.state('contacts.detail', {
// url will become '/contacts/detail'
url: '/detail',
//...more
})
Reference: https://github.com/angular-ui/ui-router/wiki/nested-states-&-nested-views#abstract-state-usage-examples

Related

AngularJS UI Router: ui-sref not updating URL in address bar?

I'm building an AngularJS app and I'm using UI-Router in order to navigate through the app.
The flow of the web app consist in first registering or login, then it takes you to a main grid that has a lot of elements that are being displayed through ng-repeat and when you click in one of them it takes you to a dashboard that displays information of the element that has been clicked and it also successfully changes the path to index.html#!/dashboard/(here goes the name of the element)
This is the html 5 code of that main grid:
<div class="container">
<div class="row" ng-controller="ribtStateServicesController" >
<div class="col-md-3 ribt_HomeGrid" ng-repeat="estado in estados" >
<div class="img-ribt_overlay" >
<a ng-click="doWork(estado.idState)" ui-sref="dashboard({ribtNameState: estado.idState})">
<img src="{{estado.image}}" class="img-thumbnail">
<div class="ribt_overlay" ></div>
</a>
</div>
</div>
</div>
</div>
However, in that same dashboard I have a side menu, that has the same elements that were used in the main grid before. So I figured that it would take the same logic to be able to use the params that the UI-Router offer in order to change the URL and the content displayed. But it does nothing.
This is the code in the HTML of the dashboard's side menu:
<div class="col-md-6 nopadding" ng-repeat="estado in estados | filter:busqueda">
<md-card md-ink-ripple="#ffffff">
<img ng-src="{{estado.nolabel}}" class="md-card-image ribt_estado_side_img"
ui-sref="dashboard({ribtNameState: estado.idState})"
alt="Estado" ng-click="doWork(estado.idState); toggleLeft()">
<md-card-title class="nopadding">
<md-card-title-text>
<p class="ribt_card_estado_nombre">{{estado.nombre}}</p>
</md-card-title-text>
<md-menu>
<md-button class="md-icon-button float-right" aria-label="Share" ng-click="$mdMenu.open()">
<i class="material-icons">more_vert</i>
</md-button>
<md-menu-content width="4" ng-mouseleave="$mdMenu.close()">
<md-menu-item ng-repeat="item in [1, 2, 3]">
<md-button>
Option {{item}}
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</md-card-title>
</md-card>
</div>
Heres is the code in my app config:
ribtApp.config(function ($stateProvider,$mdThemingProvider,$locationProvider) {
$stateProvider
.state('login', {
url: '',
templateUrl: 'ribtComponents/ribtLogin/ribtLogin.html',
controller: 'ribtLoginController'
})
.state('home', {
url: '/home',
templateUrl: 'ribtComponents/ribtHome/ribtHome.html',
controller: 'ribtStateServicesController'
})
.state('dashboard', {
url: '/dashboard/{ribtNameState}',
templateUrl: 'ribtComponents/ribtDashboard/ribtDashboard.html',
controller: 'ribtStateServicesController',
resolve:{
ribtNameState: ['$stateParams', function($stateParams){
return $stateParams.ribtNameState;
console.log($stateParams.ribtNameState)
}]
}
});
I tried a console log to see if the param was being changed and it is but it does nothing to the URL path. I've tried a lot of code that I've found in stackoverflow but none of them has worked. I would be deeply thankful if you could help me with this.
You need to switch your ng-hrefs to ui-srefs, which is what ui-router uses to set up links to change states. So something like...
<div class="col-md-6 nopadding" ng-repeat="estado in estados | filter:busqueda">
[...]
<a ng-click="doWork(estado.idState)" ng-href="index.html#!/dashboard/{{estado.idState}}">
should be something more like...
<div class="col-md-6 nopadding" ng-repeat="estado in estados | filter:busqueda">
[...]
<a ng-click="doWork(estado.idState)" ui-sref="dashboard({ribtNameState: estado.idOrWhatever})">
with the caveat that I don't know what doWork is actually doing, so I don't know if that is necessary.
If you need to transition in a controller, you can also inject $state and use $state.go(...), but most of the time ui-srefs can get it handled in my experience.

AngularJS states and dynamic templates based on criteria

I'm trying to use AngularJS + ui-router in my project, it is working tho but I am in the middle of a situation here...
I have a HOME state with url /, and that state needs to do the following:
When user is NOT logged in, I want to show a full page with a login form and some different index.html because I don't need some columns and stuff.
When the user IS logged, then the default index.html should be used so I can use my ui-view grid system with all the cool stuff when a user is logged (navbar, search forms and a lot more which are in index.html as they must be shown in every page).
In order to check if the user is logged I have a factory AuthFactory.isUserLogged()
This is what I have done but is not exactly what I want...
index.html
<div ng-cloak="" ng-if="$root.globals.currentUser">
<div class="ui fixed inverted menu">
<div class="ui container">
<a class="header item" href=""><img class="logo" src="">Dashboard</a>
<a class="item">Link</a>
<div class="right menu">
<div class="ui dropdown icon item">
{{ $root.me.username }}
<div class="menu">
Settings
<div class="divider"></div>
Logout
</div>
</div>
</div>
</div>
</div>
<div class="pusher">
<div class="full height">
<div class="ui main container" ui-view="mainContainer"></div>
</div>
</div>
</div>
<div ng-cloak="" ng-if="!$root.globals.currentUser" ui-view="mainContainer"></div>
As you can see, ui-view="mainContainer" is declared twice in the same index.html one for user logged and one when not ($root.globals.currentUser)
app.js
$stateProvider
.state('home', {
url: '/',
views: {
'mainContainer': {
templateUrl: 'views/main.html',
controller: 'HomeCtrl',
controllerAs: 'vm'
}
}
})
I know this isn't a good solution, that's why I am asking for a better one...
PS: It doesn't really matter which index.html I use, I just don't need whole markup in my not-logged-home, just a simple login form without navbar and stuff
EDIT:
This isn't working, even the console.log, it doesn't output anything
.state('home', {
url: '/',
views: {
'mainContainer': {
templateUrl: function (AuthFactory) {
if (AuthFactory.isUserLogged()) {
console.log("yep");
return 'views/main.html';
}
console.log("nope");
return 'views/login.html';
}
}
}
})
Make two different state for login and home. When user is not logged in call login state and after login home page. Only one on master page.
Then for later transition after login you need to define another on home html page.
$stateProvider
.state('login',
{
url: '/login',
templateUrl: "Account/Login.html",
controller: 'LoginController'
})
.state('home',
{
url: '/home',
templateUrl: "Home/Home.html",
controller: 'HomeController'
})

How to load/render nested UI-Views in UI-Router

I have an application with one page called index.html. This page is the main page inside the application which I load my partials into.
Here is my Index.html:
<body>
<!--<div id="view" ng-view></div>-->
<div id="view" ui-view></div>
</body>
I want to load a Partial into this but then a partial into the partial i have just added.
The partial i want to add in is called dashboard.html and should be called when /dashboard routing is hit. Then I want to load a partial into the UI-View inside dashboard.html.
I don't know what other information I would need to supply to make this happen?
EDIT:
.state('dashboard', {
url: '/dashboard',
templateUrl: 'partials/dashboard.html',
controller: 'dashboard'
})
.state('dashboard.item', {
//url: '/dashboard/calender',
templateUrl: 'partials/calender.html',
controller: 'aceTrackerDash'
})
Its good to define nested states for this purpose . When the application is in a particular state — when a state is "active" — all of its ancestor states are implicitly active as well. Below, when the "contacts.list" state is active, the "contacts" state is implicitly active as well, because it's the parent state to "contacts.list" . So all nested defined views are loaded in their proper position:
Example :
$stateProvider
.state('contacts', {
templateUrl: 'contacts.html',
controller: function($scope){
$scope.contacts = [{ name: 'Alice' }, { name: 'Bob' }];
}
})
.state('contacts.list', {
templateUrl: 'contacts.list.html'
});
<!-- index.html -->
<body ng-controller="MainCtrl">
<div ui-view></div>
</body>
<!-- contacts.html -->
<h1>My Contacts</h1>
<div ui-view></div>
<!-- contacts.list.html -->
<ul>
<li ng-repeat="contact in contacts">
<a>{{contact.name}}</a>
</li>
</ul>
Plunker : http://plnkr.co/edit/7FD5Wf?p=preview
Also take a look at this :
Angular-UI Router: Nested Views Not Working

angularjs - array updated but view did not update when using ui-router

I use ui-router to route to particular sub page as needed:
var myApp = angular.module("myApp",['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('usergroups', {
url: "/usergroups",
templateUrl: "pages/usergroups.html",
controller : 'UsergroupsCtrl'
})
.state('usergroups.create', {
url: "/create",
templateUrl: "pages/usergroups.new.html",
controller : 'UsergroupsCtrl'
})
...
This is my usergroups.html:
<body>
<h3>User Groups</h3><br/>
<button class="fon-btn" type="button" ng-hide = "toAdd" ng-click="toAdd = true" ui-sref="usergroups.create">Create New Group</button>
<div ui-view></div>
<ul>
<li class="bitcard padding10" ng-repeat="group in usergroups">
<span class="padding10"><strong>{{group.name}}</strong></span>
</li>
</ul>
</body>
and usergroups.new.html:
<body>
<form ng-submit="add()">
<input class="btn" type="submit" value="Add Usergroup"><br/><br/>
</form>
</body>
When I click on Add Usergroup, it will called add() from UsergroupsCtrl:
$scope.add = function() {
$scope.usergroups.push({name:$scope.name});
console.log($scope.usergroups);
}
The console show that $scope.usergroups is already updated. but somehow in usergroups.html: ng-repeat="group in usergroups" did not update the view. I add $scope.$apply() and $scope.$digest() but got an error:
$apply already in progress
But everything works fine if I did not use ui-router. How can I resolve this?
I think same $scope cannot be used in two different controllers. you can change it to $rootScope. like $rootScope.usergroups.push(). This SO may help you. You can use $stateParam also.

Wrap HTML to all templates/partials in angularjs but not in index.html not in partial.html

Current
index.html
<body>
<div id="container" >
<div id="modal" >
</div>
<div class="wrapper mobileWrapper">
<!-- ui-view contains visible(window) of webpage -->
<div ui-view=""></div>
</div>
</div>
</body>
header.html
<header>
Header
</header>
footer.html
<footer>
Header
</footer>
mainPage.html - partial/template
<div ng-include="'header.html'"></div>
<div> Current Page Contents </div>
<div ng-include="'footer.html'"></div>
I need to keep only <div ui-view=""></div> inside index.html and need to move remaining tags somewhere inside.
In the above example if I used ng-include then tags opened in header.html needs to be closed in header only.
Is there any alternative ideas
Edit: I got one solution
Before I'm using
// Before main.html loading
angular.module 'ngApp'
.config ($stateProvider) ->
$stateProvider
.state 'home',
url: '/'
templateUrl: 'app/views/main/main.html'
controller: 'MainCtrl'
// Problem Solved: before wrapped with wrapper.html
angular.module 'ngApp'
.config ($stateProvider) ->
$stateProvider
.state 'wrapper',
abstract: true,
templateUrl: 'app/views/main/wrapper.html'
.state 'wrapper.home',
url: '/'
templateUrl: 'app/views/main/main.html'
controller: 'MainCtrl'
Is there any way to wrap some html for all views.
not in index.html
and
not in main.html(partial)
Edit 2:
Before my states like
.state 'home',
.state 'about-us',
to wrap html I created on abstract state
.state 'wrapper',
abstract: true,
templateUrl: 'app/views/main/wrapper.html'
then I prefixed parent state(wrapper) to all other states
.state 'wrapper.home',
.state 'wrapper.about-us',
Is there any way to do it without creating a parent state(wrapper)

Categories