I have nested abstract view in my angular js project.
I got Error : Cannot transition to abstract state 'main.middle' when i move to nested abstract view.
My html code is as below:
<!DOCTYPE html>
<html ng-app="nesting">
<head>
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script data-require="ui-router#*" data-semver="0.2.10" src="https://rawgit.com/angular-ui/ui-router/0.2.10/release/angular-ui-router.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="testController">
href:
<br />
#/alpha
#/beta
#/gama
<button ng-click="moveToMiddle()">move to middle</button>
<br />
ui-sref:
<br />
<a ui-sref="main.middle.alpha">main.middle.alpha</a>
<a ui-sref="main.middle.beta">main.middle.beta</a>
<a ui-sref="main.middle.gama">main.middle.gama</a>
<hr />
<div ui-view=""></div>
<script>
'use strict';
var $urlRouterProviderRef = null;
var $stateProviderRef = null;
var app = angular.module('nesting', [
'ui.router'
]);
app.config(function( $urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/alpha');
$stateProvider
.state('main', {
url: "",
abstract: true,
template: '<div><h3>Main</h3><div ui-view=""></div></div>',
})
.state('main.middle', {
url: "",
abstract: true,
template: '<div><h4>Middle</h4><div ui-view=""></div></div>',
})
.state('main.middle.alpha', {
url: "/alpha",
template: '<div><h5>The leaf: {{state.name}}</h5></div>',
controller: function ($scope, $state){
$scope.state = $state.current;
},
})
.state('main.middle.beta', {
url: "/beta",
template: '<div><h5>The leaf: {{state.name}}</h5></div>',
controller: function ($scope, $state){
$scope.state = $state.current;
},
})
.state('main.middle.gama', {
url: "/gama",
template: '<div><h5>The leaf: {{state.name}}</h5></div>',
controller: function ($scope, $state){
$scope.state = $state.current;
},
})
;
});
app.controller('testController', function ($scope, $state) {
$scope.moveToMiddle = function () {
$state.go('main.middle');
}
})
</script>
</body>
</html>
When I click on move to middle button I got error.
How to move to abstract view?
I have referred this but its not useful in my case.
You never go to an abstract state. From the docs:
An abstract state can have child states but can not get activated itself. An 'abstract' state is simply a state that can't be transitioned to. It is activated implicitly when one of its descendants are activated.
If you define main.middle.alpha, main.middle.beta, and main.middle.gama as not abstract, you can transition to those.
As mentioned in angualr docs
An abstract state can have child states but can not get activated
itself. An 'abstract' state is simply a state that can't be
transitioned to. It is activated implicitly when one of its
descendants are activated.
app.controller('testController', function ($scope, $state) {
$scope.moveToMiddle = function () {
$state.go('main.middle.alpha');
}
as abstract state cannot be instantiated and can't viewed. if you want to access then remove abstract line
Related
In the below code, I'm trying to get a console log in the Directive (child scope),I need to get scope details.I tried adding a scope variable to the function in the directive also, but didn't work.
How can I fix this?
myDirective.html
<html ng-app="MyAppdr">
<head>
<script src="angular.js"></script>
<script src="appdr.js"></script>
</head>
<body ng-controller="dirCtrl">
<h1>hello</h1>
<employee-card></employee-card>
<!--div employee-card></div>
<div class="employee-card"></div--->
</body>
<html>
employee_info.html
<b>{{employee.name}}</b> - {{employee.job}}
<br/><br/>
<div ng-show='!!employee.followers'>
followers
<ul>
<li ng-repeat='name in employee.followers'>{{name}}</li>
</ul>
<button ng-click="follow('Galaa')">follow</button>
</div>
</div>
appdr.js
name="MyAppdr";
requires=[];
appdr=angular.module(name,requires);
appdr.controller("dirCtrl",function($scope){
console.log("This is controller dirCtrl");
$scope.employee={
name:"subo",
job:"cat",
followers:["chin","adyakshaka","aluu"]
}
console.log("parent ",$scope);
/*
$scope.follow=function(name){
$scope.employee.followers.push(name);
}
*/
});
appdr.directive("employeeCard",function(){
//$scope.employee={};
console.log("child ",$scope);
return{
templateUrl:'employee_info.html',
restrict:"AEC",
//replace:true,
controller:function($scope){
$scope.follow=function(name){
$scope.employee.followers.push(name);
}
},
scope:true
}
});
For your particular case, using scope: false seems to be sufficient if you are not showing multiple cards in same page.
appdr.directive("employeeCard",function() {
return {
scope: false,
// other attributes
If you need to show multiple cards in same page, use isolated scope and pass in
appdr.directive("employeeCard",function() {
return {
scope: {
employee: '='
},
// other attributes
<employee-card employee="employee"></employee-card>
Move the console.log() inside the controller of the directive.
appdr.directive("employeeCard", function() {
return {
templateUrl: 'employee_info.html',
restrict: "AEC",
//replace:true,
controller: function($scope) {
console.log("child ", $scope);
$scope.follow = function(name) {
$scope.employee.followers.push(name);
}
},
scope: true
}
});
If you will have only one employee card on the page then keep scope: true else if you need to show multiple cards in the same page, use an isolated scope and pass it in the template.
appdr.directive("employeeCard", function() {
return {
templateUrl: 'employee_info.html',
restrict: "AEC",
//replace:true,
controller: function($scope) {
console.log("child ", $scope);
$scope.follow = function(name) {
$scope.employee.followers.push(name);
}
},
scope: {
employee: "="
}
}
});
And in the html use something like
<employee-card employee="employee"></employee-card>
Refer the documentation of directive here
https://plnkr.co/edit/oo05d6H6AxuJGXBAUQvr?p=preview
I have created an array of items and when I click on each item details page will be displayed ,for all the items in the array I have used same details page,can anyone look at my plunker and explain why the templateURL is not working when I click on an item?
var app = angular.module("myApp", ["ngRoute"]);
app.controller('mobileController', function($scope) {
$scope.items = [{
name: 'Iphone',
}, {
name: 'Oneplus'
}, {
name: 'Moto'
}];
});
app.config(function($routeProvider) {
$routeProvider
.when('/item/:itemName', {
templateUrl: 'details.html',
controller: 'ItemCtrl'
});
app.controller('ItemCtrl', ['$scope', '$routeParams',
function($scope, $routeParams) {
$scope.itemName = $routeParams.itemName;
}
]);
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<script src="script.js"></script>
<body ng-app="myApp" ng-controller="mobileController">
<h2> Welcome to Mobile Store</h2>
<p>Search:<input type="text" ng-model="test"></p>
<ul>
<li ng-repeat="item in items|filter:test">{{ item.name }}
</li>
</ul>
<div ng-view></div>
</body>
</html>
here is my details page
<!DOCTYPE html>
{{itemName}}
is it because of a mismatch?
.when('/item/:itemName', {
a href="/items/{{item}}"
there's an extra s there
Summary of problems:
Your ItemCtrl is currently defined inside your module's config function. Move it out of there
app.config(function($routeProvider) {
$routeProvider
.when('/item/:itemName', {
templateUrl: 'details.html',
controller: 'ItemCtrl'
});
}); // you were missing this
app.controller('ItemCtrl', ['$scope', '$routeParams',
Your route is /item/:itemName and since you're not using HTML5 mode, you need to create your href attributes with a # prefix. For example
ng-href="#/item/{{item.name}}"
Fixed demo here ~ https://plnkr.co/edit/rKHsBMFcXqJUGp8Blx7Q?p=preview
I am relatively new to Angularjs, and am building a website. When I try to inject todo.html into the body tags of index.html nothing happens. I am not getting any errors in the console. I have read many of the similar posts to mine, and have already tried
Remove the ng-include from the body of index.html
Moved the links for angualrjs and bootstrap from the body of index.html to the head
Originally I used Ng-route but it did not work, so I implemented ui-router
I have tried both ng-route and ui-router,and both run without any errors. I don't think it has anything to do with either.
index.html
<html ng-app="todoApp">
<head>
<!-- META -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"><!-- Optimize mobile viewport -->
<title>Todo App</title>
<!-- Angular ans JS links-->
<script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="app/app.js"></script>
<script src="app/services/todo.service.js"></script>
<script src="app/controllers/todo.controller.js"></script>
<!-- <script src="vendor/angular-route/angular-route.min.js"></script>-->
<!--Jquery and Bootstrap Links-->
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://npmcdn.com/tether#1.2.4/dist/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/js/bootstrap.min.js" integrity="sha384-VjEeINv9OSwtWFLAtmc4JCtEJXXBub00gtSnszmspDLCtC0I4z4nqz7rEFbIZLLU"
crossorigin="anonymous"></script>
<!-- css links -->
<link href="vendor/bootstrap-css-only/css/bootstrap.min.css" rel="stylesheet"><!-- load bootstrap -->
<link rel="stylesheet" href="assets/css/todoApp.css">
<link rel="stylesheet" type="text/css" href="assets/css/Header-Picture.css">
</head>
<body >
<div ng-include="'app/views/header.html'"></div>
<!--<div ng-include="'app/views/footer.view.html'"></div>
-->
<ui-view></ui-view>
<!--<div ui-view></div>-->
</body>
</html>
App.js
var todoApp = angular.module('todoApp', [
'ui.router'
]);
todoApp.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('todo', {
url: "/",
templateUrl: 'views/todo.html',
controller: 'TodoController'
})});
todo.controller.js
todoApp.controller('TodoController', ['$scope', 'Todos', function TodoController($scope, Todos) {
$scope.formData = {};
console.log("in the TodoController");
// when landing on the page, get all todos and show them
Todos.get()
.success(function(data) {
$scope.todos = data;
});
// when submitting the add form, send the text to the spring API
$scope.createTodo = function() {
if(!$scope.todoForm.$valid) {
return;
}
Todos.create($scope.formData)
.success(function(data) {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.todos.push(data);
});
};
// delete a todo after checking it
$scope.deleteTodo = function(id) {
Todos.delete(id)
.success(function(data) {
angular.forEach($scope.todos, function(todo, index){
if(todo.id == id) {
$scope.todos.splice(index, 1);
}
});
});
};
// when submitting the add form, send the text to the node API
$scope.saveTodo = function(todo) {
Todos.update(todo)
.success(function(data) {
$scope.editedTodo = {};
});
};
$scope.editedTodo = {};
$scope.editTodo = function(todo) {
$scope.editedTodo = todo;
}
$scope.revertTodo = function() {
$scope.editedTodo = {};
}
}]);
You should be using otherwise to force the first state to be loaded as below
app.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('todo', {
url: "/",
templateUrl: 'todo.html',
})
$urlRouterProvider.otherwise('/');
});
Your index.html will look like
<div ng-include="'app/views/header.html'"></div>
<ui-view>
</ui-view>
LIVE DEMO
I added the code posted by #Aravind to my project which I belive was an improvement on my own and was correct. But the issue was the file path to the todo.html. The file path in the original was views/todo.html
the correct path is app/views/todo.html
My original code:
todoApp.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('todo', {
url: "/",
templateUrl: 'views/todo.html',
controller: 'TodoController'
})});
Current Working Code
todoApp.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('todo', {
url: "/",
templateUrl: 'app/views/todo.html',
})
$urlRouterProvider.otherwise('/');
});
I'm trying to make a custom directive that will show some elements that i previously declared in the MainController
HTML body:
<body ng-app="myApp" ng-controller="MainController">
<h1> Choose your Car </h1>
<div ng-repeat="car in cars">
<my-pattern info="car"></my-pattern>
</div>
<script src="js/MainController.js"></script>
<script src="js/myPattern.js"></script>
</body>
MainController:
angular.module('myApp').controller('MainController',function($scope) {
$scope.cars=[
{
icon: 'imgs/lamborghini.jpg',
name: 'Lamborghini',
price: 100000
},
{
icon: 'imgs/audi.png',
name: 'Audi',
price: 80000
}
];
});
Custom Directive
angular.module('myApp').directive('myPattern', function() {
return{
restrict: 'E',
scope: {
info: '='
},
templateUrl: 'js/directives/myPattern.html'
};
});
Template:
<img ng-src="{{info.icon}}">
<h2>{{info.name}}</h2>
<p>{{info.price}}</p>
If i don't use the directive but i just make the output whit the expressions <h2>{{car.name}}</h2> like this it work but with the custom directive it doesn't show me nothing.
I have all in different files.
This is working for me. There must be a issue with the location of your template with respect to your current HTML:
var app = angular.module("myApp", []);
angular.module('myApp').controller('MainController', function($scope) {
$scope.cars = [{
icon: 'imgs/lamborghini.jpg',
name: 'Lamborghini',
price: 100000
}, {
icon: 'imgs/audi.png',
name: 'Audi',
price: 80000
}];
});
angular.module('myApp').directive('myPattern', function() {
return {
restrict: 'E',
scope: {
info: '='
},
templateUrl: 'js/directives/myPattern.html'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainController">
<h1> Choose your Car </h1>
<div ng-repeat="car in cars">
<my-pattern info="car"></my-pattern>
</div>
<script type="text/ng-template" id="js/directives/myPattern.html">
<img ng-src="{{info.icon}}">
<h2>{{info.name}}</h2>
<p>{{info.price}}</p>
</script>
</div>
I solved, i didn't synchronize the directives in the Custom Directive and in the body HTML. The code was right but i make a mistake with the calling script of the directive:
<script src="js/directives/myPattern.js"></script>
//index.html
<html>
<head>
<link rel="import" href="test-table.html">
</head>
<body>
<template is="dom-bind" id="index">
<test-table data="{{data}}" ></test-table>
</template>
</body>
</html>
Polymer({
is: "test-table",
properties : {
data : {type : Array},
}
/*I dont know where should I put this stuff
"queryForIds:"
"getByIds :"
"set:"
"length:0"
*/
});
<dom-module id="test-table">
<template>
<paper-datatable-card id="datatableCard" header="Users" page-size="10" data-source="{{data}}" id-property="_id" selected-ids="{{selectedIds}}">
<paper-datatable id="datatable" data='{{data}}' selectable multi-selection selected-items="{{selectedItems}}">
<paper-datatable-column header="Id" property="_id" sortable>
<template>
<span>{{value}}</span>
</template>
</paper-datatable-column>
</paper-datatable>
</paper-datatable-card>
</template>
</dom-module>
as part of single page application I am using “paper-datatable-card” in my own custom-tag. I able to display the records but I’m not getting where I have to put the code for pagination. And I don’t want to put all records into dataSource at a time.
Any help is appreciated,
Thank you,
Venkat.
From within your Polymer component, you can set data in the ready method:
ready: function() {
this.data = {
queryForIds: function(sort, page, pageSize){
// implement me
},
getByIds: function(ids){
// implement me
},
set: function(item, property, value){
// implement me
},
length:0
};
}
Your comment question:
So I am unable to put the code from lines 117 to 133 in my custom elements as it doesnt support dom-bind
Answer (in Polymer 2.0) you can do it in your component constructor all the methods and all the data variables:
class YourComponent extends Polymer.Element {
contructor() {
super();
//in case if you use paper-datatable-card
this.data = {
get: function (sort, page, pageSize) {
return new Promise((resolve, reject) => {
const exampleData = [
{ 'name': 'someName1' },
{ 'name': 'someName2' }
];
resolve(exampleData);
});
},
set: function(item, property, value){...},
length: 1
};
//in case if you use paper-datatable only then without get or set properties
this.data = [ { name: 'someName' } ];
}
}