Nested Views with Dynamic Id's Angular & Rails - javascript

Hey I have Angular rendering a list of Quotes as resources. The Quotes are stored in a rails back end. I am at the point where I would like to use Angular to render the show.html for that specific quote resource.
I havent been able to get angular to resolve to the state.
I'm not sure if I understand how to pass id's into state.
I need help figuring out how to get angular to render the show.html in the ui-view labeled "fullquote" for the specific quote. Here is my code.
Quotes.html
<div class="quotes col-xs-10 col-md-8" ng-controller="QuotesCtrl" >
<div ng-repeat="quote in quotes">
<a ng-click="showQuote(quote);">
<span ng-if="quote.read == false"> *NEW*</span>
<span>Quote id: {{quote.id}}</span>
<span>Name: {{quote.name}}</span>
<span>Email: {{quote.email}}</span>
<span>City: {{quote.city}}</span>
<span>Region: {{quote.region}}</span>
<span>State: {{quote.state}}</span>
</a>
<div ng-show="quote.visible">
<a ui-sref="quotes/{{quote.id}}"> View </a>
<ui-view="fullquote"></ui-view="fullquote">
<a ng-click="quotes.splice($index, 1)"> Delete </a>
<div ng-if"">
<span> {{quote.question2 }}</span>
<span> {{quote.question3 }}</span>
<span> {{quote.question4 }}</span>
<span> {{quote.question5 }}</span>
<span> {{quote.question6 }}</span>
<span> {{quote.question7 }}</span>
<span> {{quote.question8 }}</span>
<span> {{quote.question9 }}</span>
<span> {{quote.question10 }}</span>
<span> {{quote.question11 }}</span>
<span> {{quote.question12 }}</span>
<span> {{quote.question13}}</span>
</div>
</div>
</div>
</div>
Quotes.js
app.factory('Quotes', ['$resource',function($resource){
return $resource('/quotes.json', {},{
query: { method: 'GET', isArray: true },
create: { method: 'POST' }
})
}]);
app.factory('Quote', ['$resource', function($resource){
return $resource('/quotes/:id.json', {}, {
show: { method: 'GET' },
update: { method: 'PUT', params: {id: '#id'} },
delete: { method: 'DELETE', params: {id: '#id'} }
});
}]);
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', { url: '', templateUrl: 'static_pages/home.html'})
.state('quotes', { url: '/quotes', abstract: false, views : { templateUrl: 'quotes.html', controller: 'QuotesCtrl'}})
.state('quotes/:id', { url: 'quotes/:id', view: { "fullquote": { templateUrl: 'show.html', controller: 'QuotesCtrl'}}})
.state('quotes/:id.pdf', { url: 'quotes/:id.pdf', controller: 'QuotesCtrl'})
.state('users', { url: '/users', templateUrl: 'users.html', controller: 'UsersCtrl'})
.state('/users/:id', { url: 'users_show.html', controller: "UsersCtrl" });
$urlRouterProvider.otherwise( function($injector, $location) {
var $state = $injector.get("$state");
$state.go("home");
})
$locationProvider.html5Mode({ enabled: true, requireBase: false });
});
app.controller("QuotesCtrl", ['$scope', '$state', '$http', 'Quotes', 'Quote', '$location', function($scope, $state, $http, Quotes, Quote, $location ) {
$scope.quotes = Quotes.query();
$scope.quote = Quote.query();
$scope.showQuote = function (quote) {
quote.visible = !quote.visible;
}
}]);

There are several things you should look into:
Your state naming is incorrect. I assume you are trying to use nested states.In this case you need to have quotes.detail or something of the kind. Also, in the state, you need to name your object views instead of view. Please, refer to UI.Router multiple views guide for more information.
.state('quotes.detail',
{ url: 'quotes/:id',
views: {
"fullquote": { templateUrl: 'show.html',
controller: 'QuoteCtrl'}
}
})
To pass a parameter to the state you need to change your link to this. If you'd like to know more about passing parameters to ui.router states - read the manual:
<a ui-sref="quotes.detail({{quote.id}})"> View </a>
If you want to have a separate view, you also need to have separate controller for it. I named it it QuoteController. You can get ht :id from the URL by injecting $stateParams in the controller. More info about getting parameters into the controllers - here:
//QuoteController
['$stateParams, Quote , function($stateParams, Quote) {
Quoute.get({id:$stateParams.id});
}]
I'm not sure this will completely solve your problem, but it will certainly bring you closer to solving it. I hope I was helpful!

Related

how to know who called the controller

I have a file which has different type of code for different purposes. and I want them to be called when the controllerAs is having a specific value. I tried many previous answers but most of them are for the controller but I want to know the value of controllerAs. so how can I know the value of controllerAs and how can I use it in an if condition??
var challenge_page = {
name: "web.challenge-main.challenge-page",
parent: "web.challenge-main",
url: "/challenge-page/:challengeId",
templateUrl: baseUrl + "/web/challenge/challenge-page.html",
controller: 'ChallengeCtrl',
controllerAs: 'challenge',
redirectTo: "web.challenge-main.challenge-page.overview",
var participate = {
name: "web.challenge-main.challenge-page.participate",
parent: "web.challenge-main.challenge-page",
url: "/participate",
templateUrl: baseUrl + "/web/challenge/participate.html",
controller: 'ChallengeCtrl',
controllerAs: 'participate',
title: 'Participate',
};
In the above code block, I have the directive file two pages. which calls the same controller.
$state.current will give you current state information. You can use $state.current.name or $state.current.title or any unique attribute specific to the state... to identify the current page inside controller.
angular.module('app', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider) {
const challenge_page = {
name: "challenge-page",
url: "/challenge-page/:challengeId",
templateUrl: "/web/challenge/challenge-page.html",
controller: 'ChallengeCtrl',
controllerAs: 'challenge',
title: 'Challenge'
};
const participate = {
name: "participate",
parent: "challenge-page",
url: "/participate",
templateUrl: "/web/challenge/participate.html",
controller: 'ChallengeCtrl',
controllerAs: 'participate',
title: 'Participate'
};
$urlRouterProvider.otherwise('/challenge-page/1');
$stateProvider
.state(challenge_page)
.state(participate);
})
.run(function($templateCache) {
$templateCache.put("/web/challenge/challenge-page.html", `
<h1>ChallengePage</h1>
<ul>
<li><strong>State Name: </strong>{{challenge.currentState.name}}</li>
<li><strong>Title: </strong>{{challenge.currentState.title}}</li>
</ul>
<hr />
<blockquote>
<ui-view></ui-view>
</blockquote>
`);
$templateCache.put("/web/challenge/participate.html", `
<h1>Participate</h1>
<ul>
<li><strong>State Name: </strong>{{participate.currentState.name}}</li>
<li><strong>Title: </strong>{{participate.currentState.title}}</li>
</ul>
`);
})
.controller('ChallengeCtrl', function($state) {
this.currentState = $state.current;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.24/angular-ui-router.min.js"></script>
<div ng-app="app">
<a ui-sref="challenge-page({challengeId: 1})" ui-sref-active="active">Challenge</a>
<a ui-sref="participate" ui-sref-active="active">Participage</a>
<ui-view></ui-view>
</div>

Nested Angular ui routers throw exception

I've got this error when clicking on ui-sref="favorite-list":
Could not resolve 'favorite-list' from state 'studies'
I have code like this:
$stateProvider
.state('study', {
url: '/study/:studyId',
templateUrl: 'scripts/study/study-edit.template.html',
controller: 'StudyController'
})
.state('studyObject', {
url: '/study/:studyId/studyObject/:studyObjectId',
templateUrl: 'scripts/study-object/study-object-edit.template.html',
controller: 'StudyObjectController'
})
.state('studies', {
url: '/studies?all&field&term&page&sort&sort_dir',
templateUrl: 'scripts/studies/studies.template.html',
controller: 'StudiesController',
onExit: function exitStudies(filterQuery) {
filterQuery.emptyQuery();
},
menuElement: 'studies',
resolve: {
attributes: function (attribute, manageAttributes) {
...
}
}
})
.state({
name: 'studies.favorite-list',
template: '<favorites-list></favorites-list>',
parent: 'studies'
});
and html:
<div class="left-menu" ng-class="{collapsed: menu.isCollapsed}" click-outside="closeMenu()">
<ul class="list-unstyled">
<li>
<button role="button" ui-sref="favorite-list" ng-class="{'text-bold': favorites.active}">
<img src="images/divos/star.svg" alt="Favorites" height="20" width="30"> Favorites
</button>
</li>
</ul>
<div ui-view></div>
</div>
I've try with parent and without, using .state('studies.favorite-list', {}) also using ui-sref="studies.favorite-list" but I'm keep getting this error. I'm using version 0.2.18 from bower.
Found the solution, I've only needed to add comma before the name:
ui-sref=".favorite-list"

UI-Router nested state view not rendering (rendering parent view)

Using ui-router in angular, I have setup a 'users' state where all the users in my application are returned in an ng-repeat. I am trying to create the show state for the users profile page however the view of the child state is inheriting the parent view 'templates/users/index.html' (Here is my app.js:
.state('users', {
abstract: true,
name: 'users',
url: '/users',
views: {
nav: {
templateUrl: 'templates/navbar.html',
controller: 'MainCtrl'
},
content: {
templateUrl: 'templates/users/index.html',
controller: 'UsersCtrl'
}
}
})
.state('users.show', {
url: '/show/:id',
views: {
nav: {
templateUrl: 'templates/navbar.html',
controller: 'MainCtrl'
},
content: {
templateUrl: 'templates/users/show.html',
controller: 'UsersCtrl'
}
}
});
Here is my index.html:
<div class="container">
<label>Search: <input ng-model="searchText"></label>
<a ui-sref="users.show({id: user.id})" ng-click="showUser(user.id)" ng-repeat="user in users | filter:searchText ">
<h2> {{ user.name }} </h2>
<h3> {{ user.email }} </h3>
<button ng-click="createConversation({sender_id: current_user.id, recipient_id: user.id})" >Message</button>
</a>
</div>
The url in the browser is http://localhost:8080/#/users/show/2 however the html file being inherited in the users.show state is the parents users (index.html) file.
Any help appreciated!
The nested view users.show will actually render within the user view. So you just need to place another <ui-view> within templates/users/index.html where the show view will render.

Params with $state.go and $scope

I tried many things to pass data to my view, but i don't know what is wrong.
I tried with $scope and pass data with $state.go, but nothing happens.
.state('app.ler',
{
views: {
'menuContent': {
templateUrl: 'mensagens/mensagemRead.html',
controller: 'MensagensCtrl',
params: {'assunto': null}
}
},
url: '/ler'
})
$scope.read = function (id) {
MensagensService.ler(id).then(function (response) {
// $scope.mensagem_ler = response.data[0];
// alert(response.data[0].assunto);
$state.go('app.ler', {assunto:response.data[0].assunto});
console.log($stateParams);
});
};
<ion-view title="Mensagens2">
<ion-content class="has-header">
<div class="list">
<a class="item item-avatar" href="#">
<img src="venkman.jpg">
<h2>Gustavoaaa</h2>
<!--<p>{{mensagem_ler.assunto}}</p>-->
<p>{{assunto}}</p>
</a>
</div>
</ion-content>
</ion-view>
You can add the state parameter using a : in the url of your state.
.state('app.ler',
{
views: {
'menuContent': {
templateUrl: 'mensagens/mensagemRead.html',
controller: 'MensagensCtrl'
}
},
url: '/ler/:assunto'
});
This will make the property assunto available in $stateParams
params option of state is available in root level of state definition, you could not have them in leaf level of namedView.
.state('app.ler', {
views: {
'menuContent': {
templateUrl: 'mensagens/mensagemRead.html',
controller: 'MensagensCtrl',
}
},
url: '/ler/{assunto}', //here is parameter mentioned in URL
params: {
'assunto': null //parameter default value
}
})
You can get this values in $stateParams object inside your controller.
Try this in your state configurations
url: '/ler?assunto'
If you want to pass more parameters then just add them like this
url: '/ler?assunto&param2&param3....'
To use the state param in your view you can save it in a $scope variable in your controller and then use it.
For example: $scope.assunto = $stateParams.assunto;
<ion-view title="Mensagens2">
<ion-content class="has-header">
<div class="list">
<a class="item item-avatar" href="#">
<img src="venkman.jpg">
<h2>Gustavoaaa</h2>
<!--<p>{{mensagem_ler.assunto}}</p>-->
<p>{{assunto}}</p>
</a>
</div>
</ion-content>
</ion-view>

State.go() shows the url in address page but doesn't refresh the html view

I have a problem when whorking on Ionic with angularJs, the problem is in routing system when I try to develop a login page .
In the controller part of code i'l trying to load a welcome page calle 'dash' with state.go(psc.dash)
here is my controller.js :
angular.module('starter.controllers', [])
.controller('LoginCtrl', function($location, $state) {
var user = this;
user.login = function() {
console.log("LOGIN user: " + user.email + " - PW: " + user.password);
setTimeout(function() {
state.go('psc.dash');
}, 20);
};
})
.controller('DashCtrl', function($scope, $location) {});
here is my App.js:
.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('login', {
url: "/login",
views: {
'login': {
templateUrl: "templates/login.html",
controller: "LoginCtrl"
}
}
})
.state('psc', {
url: "/psc",
abstract: true,
templateUrl: "templates/psc.html"
})
.state('psc.dash', {
url: "/dash",
views: {
'psc-dash': {
templateUrl: "templates/dash.html",
controller: "DashCtrl"
}
}
})
;
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/login');
});
and here is my login.html
<div class="list list col span_1_of_2 " ng-controller="LoginCtrl as loginCtrl">
<label class="item item-input">
<span class="input-label">E-mail</span>
<input type="text" ng-model="loginCtrl.email">
</label>
<label class="item item-input">
<span class="input-label">password</span>
<input type="password" ng-model="loginCtrl.password">
</label>
<div>
<div class="col span_2_of_3">forgot password ? </div>
<button class="button button-positive col span_1_of_3" ng-click="loginCtrl.login()">
connect
</button>
</div>
</div>
The problem is when I click on connect button the url '/psc/dash' appears in address bar but the login view stay displayed and the page is not reloaded with the new html view.
EDIT
This is wrong. There is a discrepancy in the ui-router documentation: states that inherit from an abstract state are prefixed with their parents URL.
The reason is that although your 'psc.dash' nested state is defined as a child of the 'psc' state, the URL you have assigned to it is not automatically prefixed with its parent's URL.
You want to change the 'psc.dash' state definition to this:
.state('psc.dash', {
url: "/psc/dash",
views: {
'psc-dash': {
templateUrl: "templates/dash.html",
controller: "DashCtrl"
}
}
})
Take a look at the ui-router documentation for why this is:
What Do Child States Inherit From Parent States?
Child states DO inherit the following from parent states:
Resolved dependencies via resolve Custom data properties
Custom data properties
Nothing else is inherited (no controllers, templates, url, etc).
The service is $state so the code should be:
$state.go('psc.dash');
You can get rid of the controller definition in your HTML:
<div class="list list col span_1_of_2" ng-controller="LoginCtrl as loginCtrl">
</div>
use this instead:
<div class="list list col span_1_of_2">
</div>
and change the state this way:
.state('login', {
url: "/login",
views: {
'login': {
templateUrl: "templates/login.html",
controller: "LoginCtrl as loginCtrl"
}
}
})
You don't need to define the controller twice.
Your login.html template does not use <ion-view>. It would be interesting to see a plunker of your project.
Another things I am not sure about is the state definition. If the view login is not wrapped in another container you should write it like this:
.state('login', {
url: "/login",
templateUrl: "templates/login.html",
controller: "LoginCtrl as loginCtrl"
})
SOLUTION:
my psc route should be named 'login' to be identified
.state('psc', {
url: "/psc",
views: {
'login': {
abstract: true,
templateUrl: "templates/psc.html"
}
}
})

Categories