AngularJS two-way binding in route templates when using routeProvider templates - javascript

I have an app where the sidebar will show a list of to do messages, and a list of processed messages (navigate with tabs), and clicking on it will show the details of the message on the main section to the right of the sidebar. The view on the right has some form inputs whwere the user fills out the details of the message, press a button, and the message is moved from to-do to processed.
<div id="sidebar" data-ng-controller="MessageController">
<ul class="nav nav-tabs" id="message-tab">
<li>To-do</li>
<li>Processed</li>
</ul>
<div class="tab-content">
<div class="tab-pane" id="to-do">
<table class="table table-hover">
<tr data-ng-repeat="message in todoMessages | orderBy: id">
<td>
<span>{{message.name}} </span> <small style="float:right;">{{message.type}}</small>
</td>
</tr>
</table>
</div>
<div class="tab-pane" id="processed">
<table class="table table-hover">
<tr data-ng-repeat="message in processedMessages | orderBy: id">
<td>
<span>{{message.name}} </span> <small style="float:right;">{{message.type}}</small>
</td>
</tr>
</table>
</div>
</div>
</div>
<div id="main-panel">
<div class="message-preview " data-ng-view="">
</div>
</div>
The problem I am having is that the main section on the right uses ng-view with the $routeProvider providing the template when the URL hash changes. When trying to update a $scope object in the template view, the sidebar's lists does not update.
app.js
var app = angular.module('messageApp', []);
app.config(function ($routeProvider) {
$routeProvider
.when('/todo/:messageId',
{
controller: 'MessageController',
templateUrl: 'app/partials/todoView.html'
})
.when('/processed/:messageId',
{
controller: 'MessageController',
templateUrl: 'app/partials/processedView.html'
})
.otherwise({ redirectTo: '/' });
});
However, if I put the same markup that's in the sidebar into the template view, the two-way binding works properly as I can see that the list updates when manipulating the scope objects.
What am I doing wrong and how can I have the sidebar using ng-controller update properly?

Related

ui-router nested view could not resolve state

i try to make a nested view in my app.
This is how I try, I have parent UI-view
<div class="ui-view-container col-lg-offset-2 col-lg-10 col-md-offset-2 col-md-10 col-sm-12 col-xs-12" ng-cloak>
<div ui-view></div>
</div>
where I change all state on my web app. For example, this is one state
.state('distributorItem', {
url: '/distributorItem',
templateUrl: 'distributorItem.html',
controller: 'distributorItem',
authentication: {roles: ["distributor"]}
})
Inside this state, I want to make another MENU, where user can select item and find information by ID, below is example how I pass ID params and add child UI-view
<table class="table-hover">
<thead>
<tr>
<th>Item ID</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in itemIdInClientDetail">
<td><a ui-sref="client/info/{{value.id}}">{{value.id}}</a></td>
</tr>
</tbody>
</table>
<div class="col-lg-11 col-md-11 col-sm-10 col-xs-12">
<div ui-view></div>
</div>
There is child state
.state('distributorItem.client/info/:itemID', {
url: '/client/info/:itemID',
templateUrl: 'clientItemInfo.html',
controller: 'clientItemInfo',
authentication: {roles: ["distributor"]}
})
And this not working, because I get this error in console
angular.js:12477 Error: Could not resolve 'client/info/1126' from state 'distributorItem'
Pls, help... thnx
EDIT:
I make a change like #Maxim Shoustin answered. Now state changed, but in child navigation when I click on item, parent ui-view is full refreshed (child navigation and ui-view) not only child
now my state looks like this
.state('client', {
url: '/client/info/:itemID',
templateUrl: 'clientInfo.html',
controller: 'detailControllerClient as vm',
})
.state('client.detail', {
url: '/detail/:itemID',
templateUrl: 'itemInfoById.html',
controller: 'detailControllerClient as vm',
})
And html is here. (infoDisplay.html is parent view inside index.html. This ui-view in code bellow is child view (client.detail))
infoDisplay.html
<div class="new_nav col-lg-1 col-md-1 col-sm-2 col-xs-12">
<table class="table-hover">
<thead>
<tr>
<th>item ID</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in clientDetail">
<td><a ui-sref=".detail({'itemID': value.id})">{{value.id}}</a></td>
</tr>
</tbody>
</table>
</div>
<div ui-view></div>
You have to use this format
.state('detail', {
url: '/client/info/{itemID}',
and
ui-sref="detail({itemID: '1126'})"
for more see Give URL with ID in Angular UI Router and How to pass parameters using ui-sref in ui-router to controller
try this
.state('distributorItem', {
url: '/distributorItem',
abstract:true,
templateUrl: 'distributorItem.html',
controller: 'distributorItem',
authentication: {roles: ["distributor"]}
})
.state('distributorItem.client', {
url: '/client/info/:itemID',
templateUrl: 'clientItemInfo.html',
controller: 'clientItemInfo',
authentication: {roles: ["distributor"]}
})

Populate angular ui bootstrap popover

How do you populate an angular ui bootstrap popover? I want to populate the popover with a list of actor names. Here is the code:
<div class="container" ng-if="radioModel=='Search for Actor'">
<p>Movies played in:</p>
<table class="table table-bordered">
<tr ng-repeat="name in listOfMovies">
<td>
<p>
<button uib-popover="populateWithListOfData" popover-trigger="mouseenter" type="button" class="btn btn-default"> {{ name }}</button>
</p>
</td>
</tr>
</table>
</div>
I want to be able to populate this popover for each name of the ng-repeat. So I will get a name of a movie and based on that name I want to populate the popover with a list of actors in that movie. Thanks guys.
This is definitely possible.
I have setup a data item called friends in JS
$scope.friends = [
{name:'John'},
{name:'Jessie'},
{name:'Johanna'},
{name:'Joy'}
];
Also , an array was created for the text in the popup
$scope.toolTip =['D','A','C','T'];
If you want to display a pop up for each row.
I've created the ng-repeat and the relevant popover.In order to display all the letters in the first popover.
<div ng-repeat="f in friends">
{{f.name}}
<button uib-tooltip="{{toolTip[$index]}}" type="button" class="btn btn-default">Tooltip {{placement.selected}}</button>
</div>
Here is a working demo
How does it works?
Your tool tip value is set as uib-tooltip="{{toolTip[$index]}}".it accesses each element according to the $index obtained from ng-repeat.
If you want to display all the data in the first pop up
I've created the ng-repeat and the relevant popover.In order to display all the letters in the first popover.
<div ng-repeat="f in friends">
<div ng-if="$index==0">
<button uib-tooltip="{{toolTip}}" type="button" class="btn btn-default">Tooltip {{placement.selected}}</button>
</div>
{{f.name}}
</div>
Here is a working demo
How does it works?
Your tool tip value is set as uib-tooltip="{{toolTip}}".It enters the ng-if , if the condition is met, and thus prints the array.
I couldn't test if it works, but this might give you the idea.
(function ()
{
function moviePopover($compile)
{
return {
restrict: "EA",
scope: true,
templateUrl: '<button uib-popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" type="button" class="btn btn-default">Popover With Template</button>',
link: function (scope, element, attrs)
{
scope.dynamicPopover = {
content: "Movies",
templateUrl: "myPopoverTemplate.html",
title: "Title"
};
if (attrs.movieName !== undefined)
{
scope.movieList = getMoviesByName(attrs.movieName);
$compile(element)(scope);
//If 1st leads to infinit loop use this
// $compile(element.contents())(scope);
}
function getMoviesByName(movieName)
{
//return all moviews based on movieName
//here im just returning dummy array(you return your data)
return ["Movie1", "Movie2"];
}
}
}
}
angular.module("myApp").directive("moviePopover", ["$compile", moviePopover]);
}());
<script type="text/ng-template" id="myPopoverTemplate.html">
<ul>
<li ng-repeat="movie in movieList">{{movie}}</li>
</ul>
</script>
<div class="container" ng-if="radioModel=='Search for Actor'">
<p>Movies played in:</p>
<table class="table table-bordered">
<tr ng-repeat="name in listOfMovies">
<td>
<p>
<movie-popover movie-name="{{name}}"></movie-popover>
</p>
</td>
</tr>
</table>
</div>

Error: [ng:areq] Argument 'ActsController' is not a function, got undefined

I keep getting the error: Error: [ng:areq] Argument 'ActsController' is not a function, got undefined. I've seen several other people have similar errors, usually due to typos. But I don't think I've misspelled the controller name anywhere.
I am working with Angular and Rails, by the way.
app.js
var controllers, snowball_effect;
snowball_effect = angular.module('snowball_effect', [
'templates',
'ngRoute',
'ngResource',
'controllers'
]);
snowball_effect.config([
'$routeProvider', function($routeProvider) {
return $routeProvider
.when('/', {
templateUrl: "static_pages/index.html",
controller: 'StaticPagesController'
})
.when('/acts/index', {
templateUrl: "acts/index.html",
controller: 'ActsController'
});
}
]);
controllers = angular.module('controllers', []);
controllers.controller("StaticPagesController", ['$scope', function($scope) {}]);
controllers.controller("ActsController", [
'$scope',
'$routeParams',
'$location',
'$resource',
function($scope,$routeParams,$location,$resource) {
$scope.acts = [
{
id: 1,
name: "Plant a Flower",
description: "Plant a flower in your garden or along the street."
inspires: 1
}
];
}]);
javascript/templates/acts/index.html
<div class="actions_body">
<h2>Listing Actions</h2>
<div ng-controller="ActsController" class="body">
<table class="row">
<thead>
<tr>
<th class="col-md-offset-1 col-md-2 active">
<label>Name</label>
</th>
<th class="col-md-4">Description</th>
<th class="col-md-2">Inspires</th>
<th colspan="2" class="col-md-2">Modify</th>
</tr>
</thead>
<tbody ng-repeat="act in acts">
<td class="col-md-offset-1 col-md-2">{{act.name}}</td>
<td class="col-md-4">{{act.description}}</td>
<td class="col-md-2">{{act.inspires}}</td>
<td>Edit</td>
<td>Delete</td>
</tbody>
</table>
<br>
New Action
</div>
</div>
Edit:
Now that I think about it, I'm also having another problem. Whenever I refresh the page, the main partial vanishes. I guess this question is more Rails/Angular specific.
views/home/index.html.erb
<div ng-app="snowball_effect">
<div class="view-container">
<div ng-include="'layouts/index.html'"></div>
</div>
</div>
assets/javascript/templates/layouts/index.html
<div ng-include="'layouts/navigation.html'"></div>
<div ng-view class="view-frame animate-view"></div>
assets/javascript/templates/static_pages/index.html
<div class="body">
<div class="container">
<div class="introduction">
<h1>Welcome to Snowball Effect</h1>
</div>
<div class="body">
<h2>A social media platform that brings people together in a spirit of community service.</h2>
</div>
</div>
</div>
So, in the layout/index.html, the navigation bar loads fine, but the ng-view only after the first page load.
Is app.js included in index.html??
<script src="js/app.js"></script>

Pass object to isolated directive

When my application loads a function to get items from a server runs, this function get the title and Id of all items on the server,
then puts them in an array.
In my main html I have a table that displays this array, and when i click the title of an Item, I call another function (onView)
which gathers more information about that item from the server. This new information is passed to
a variable called '$scope.currentItem'.
I also have a directive called 'currentItem', this is used to display that item for the user.
myApp.directive('currentItem',function(){
return{
restrict:'E',
scope:{
data:'='
},
templateUrl: 'currentItem.html',
controller:function($scope){
}
};
});
To know if a user has clicked an item I have a boolean called isView, so when the function to gather more information runs
the isView is set to 'true'.
My html looks like this:
<div ng-app="myApp">
<hr>
<div ng-controller="appCtrl">
<div ng-hide="isView" class="col-md-12">
<table id="mainTable" ng-table="tableParams" class="table">
<tbody ng-repeat="item in items">
<tr>
<td id="Title" data-title="'Title'">
{{item.id}} |<a ng-click="onView(item.id)">{{item.title}}</a>
</td>
<td data-title="'Description'">
{{item.description | date:'dd-MM-yyyy'}}
</td>
<td data-title="'Created'">
{{item.created | date:'dd-MM-yyyy'}}
</td>
</tr>
</tbody>
</table>
</div>
<div ng-show="isView" class="col-md-12">
<current-item data="currentItem"></current-item>
</div>
</div>
</div>
This can't be the correct way to pass an object to a directive, seeing I always use the same 'currentItem' object.
How could I improve this, so that each object is isolated and editable in a seperate view?

AngularJS: Load dialog for ng-repeat with large number of items

I am trying to come up with a way to display a load dialog while the items in ng-repeat are being rendered. The use case is as follows:
User clicks a toggle switch to display a list of items
A directive is shown that contains an ng-repeat of items
The list of items show up almost instantly on a PC. But on a mobile device it takes a few seconds for the list to show up. This can cause the user to tap the toggle switch multiple times resulting in the list being hidden and shown.
Here's my HTML mark-up:
<div jqm-theme="b">
<div style="" jqm-theme="a" jqm-textinput ng-model="projectFilter"
placeholder="Filter Project Areas...">
</div>
<div style="height:12px;"></div>
<ul jqm-listview style="padding-top: 12px;">
<project-display title="My Project Areas" filter="projectFilter" projects="myProjects"
select-project="selectProject" show="true">
</project-display>
<li jqm-li-entry jqm-theme="b" class="ui-icon-alt">
<div class="ui-grid-a">
<div class="ui-block-a">
<a class="projTitle">Toggle All Projects</a>
</div>
<div class="ui-block-b" style="text-align:right;">
<div jqm-flip mini="true" jqm-theme="d" ng-model="allSwitch.value"
on-label="On" on-value="1" off-label="Off" off-value="0"
default-value="0" ng-click="toggleAllProj()">
</div>
</div>
</div>
</li>
<project-display title="All Project Areas" filter="projectFilter" projects="projects"
select-project="selectProject" show="allSwitch.value">
</project-display>
</ul>
</div>
Here's the directive:
angular.module('myApp').directive('projectDisplay', ['$location', function($location) {
return {
restrict: 'E',
scope: {
title: '#',
filter: '=',
projects: '=',
selectProject: '=',
show: '='
},
templateUrl: 'template/directives/project-display.html'
};
}]);
Here's the directive's template:
<div ng-show="show">
<span style="margin-left:13px" jqm-li-divider>{{title}} ({{projects.length}})</span>
<ul jqm-listview style="padding-top: 12px;">
<li jqm-li-link jqm-theme="a" style="margin-left:13px" class="ui-icon-alt" ng-click="selectProject(project)"
ng-repeat="project in projects | filter: filter">
<a>{{project.title}}</a>
</li>
</ul>
</div>
I am using Angular JQM's $loadDialog which can be shown and hidden by explicitly calling the separate methods or it can also display until a promise is resolved.
Is there a way to monitor when all items within an ng-repeat have been rendered? I appreciate any help on this matter.
Thanks

Categories

Resources