AngularJS ng-repeat display content in separate view - javascript

I'm working on a basic news feed app. What I need is for a specific news article, entry.content, to display in a separate view after a click. Both controllers have access to the data, but I need a synchronized click event so the second controller knows which specific article to display. I've been working on this for awhile & couldn't find relevant links on google or here where a secondary view was involved. I need a separate view b/c I have to add a lot more HTML to that page & eventually click(previous/next) between articles. I have an example which is working where the click event happens, but the content displays in the current view then hides after click.
I have a Plunker: http://plnkr.co/edit/lk66pRb7A6DkGM7NQKF7?p=preview
Here is the index.html code:
<body ng-app="FeedApp">
<h1>News Feed</h1>
<div ng-controller="NewsCtrl">
<div id="main">
<div ng-view=""><!-- angular yield --></div>
</div> <!-- main -->
</div> <!-- NewsCtrl -->
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="main.js"></script>
</body> <!-- FeedApp -->
Here is the home.html code:
<div ng-repeat="new in news">
<h3 ng-repeat="entry in new.entries" ng-if="$index < 3">
{{entry.title}}
</br>
Display this story</br>
Desired: click this Link, go to #/article & display this story
<p class="news-entries" ng-show="show" ng-bind-html="TrustSnippet(entry.content)"></p>
</h3>
</div> <!-- new in news -->
Currently, in the article.html file I only have a back button as I'm not sure what to put in there. All other code is in the Plunker, but I can add here if it will help.
I was thinking this might be be solved using current $index value, but I just don't know at this point.
Any help is appreciated.

You probably just want to use $routeParams like so:
here's a Plunker
route
.when("/article/:articleId", { . .
Link
<a href="#/article/{{$index}}" . . .
Param
FeedApp.controller("ArticlesCtrl", ["$scope", "$routeParams", '$http',
function($scope, $routeParams, $http) {
var index = $routeParams.articleId;
Article Object
$scope.article = $scope.news[0].entries[index];
I would omit the entries bit altogether and I would probably use a factory to manage/maintain the data.

Related

Angular ng-repeat works... but no values are bound / displayed (Twig)

I'm having some issues getting my new Angular project off the ground. I'm going to break off pieces into services and such later on, but for now I just have a controller called DashCtrl in a module called sandpiper.
I want to make a list of div.card elements from the $scope.results array within DashCtrl, additional items append to $scope.results when add-button is clicked, and also to append its $scope.test to the header. What happens, after clicking the button a few times, is this: (Screenshot link because I'm new and don't have reputation points T_T)
$scope.pushit() works and ng-repeat winds up spitting out the proper number of items, but the titles are absent. $scope.test isn't getting read either. I've banged my head against the wall for a couple of hours now and even coded up a little bare-bones Angular test to make sure I wasn't out of my gourd... but I just cannot figure this one out.
Here's my JS (two scripts, minified into /build/sandpiper.min.js later)
var app = angular.module('sandpiper', []);
app.controller('DashCtrl',['$scope',function($scope){
$scope.test = "Header"
$scope.results = [
{
title: "Test Item 1",
file: "12345978-My-Test-Document.pdf",
type: "PDF",
tags: ['pdf','test','foo','bar'],
image: "static/img/pdf.png"
}
]
$scope.pushit = function(){
$scope.results.push({
title: "Test Item 1",
file: "12345978-My-Test-Document.pdf",
type: "PDF",
tags: ['pdf','test','foo','bar'],
image: "static/img/pdf.png"
})
}
}])
And here's my HTML (unrelated portions are omitted)
<!DOCTYPE html>
<html lang="en">
<head>
(...)
<!-- bower:js -->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/materialize/bin/materialize.js"></script>
<script src="../bower_components/angular/angular.js"></script>
<!-- endbower -->
<script src="/build/sandpiper.min.js"></script>
</head>
<body ng-app="sandpiper">
<main>
<div class="container" id="content-root">
<div id="dash-wrapper" ng-controller="DashCtrl">
<h3>Test {{ test }}</h3>
<a ng-click="pushit()" class="btn-floating btn-large waves-effect waves-light" id="add-button">
<i class="material-icons">add</i>
</a>
<nav>
(...)
</nav>
<div class="row" id="results-container">
<div class="col s12 m4 l3" ng-repeat="item in results">
<div class="card">
<div class="card-content">
<span class="black-text">{{ item.title }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
(...)
</body>
</html>
Any help would be greatly appreciated; thanks in advance. Hope it's not something really stupid...
(Also this is my first post here, so if I'm doing anything wrong let me know)
Well... the issue was obvious enough. I singled out my CSS includes (I'm using Materialize) and determined that that wasn't the issue-- it was actually that I was using Twig, a PHP template engine that also uses mustache notation for variables. My bindings were being stripped right out by the backend before they even reached the browser. Cannot believe I didn't realize that.
For anyone else who's having this issue, try using a different Angular delimiter or using a different tag_variable pattern for Twig.

Angular ng-sortable - Basic example of how it works

SITUATION:
Hello guys! In my app i have a sort of kanban: there are some columns, each containing a list of items.
I need to drag and drop items among columns and reorder them inside the same column.
I have tried before three angular modules related with drag and drop (first two) and reordering (third):
ngDraggable: https://github.com/fatlinesofcode/ngDraggable
Angular dragdrop: https://github.com/codef0rmer/angular-dragdrop
Angular ui-sortable: https://github.com/angular-ui/ui-sortable
They are nice, with good documentation, but it seems not possible to drag and drop and reorder at the same time.
Then i found another module:
ng-sortable: https://github.com/a5hik/ng-sortable
It seems to be exactly what i need.
But the documentation is not so clear. I am not able to understand how to set it up.
QUESTION:
Can you show me please how to set it up?
There is a plunker with a good and clear example?
Thank you!
Minimal ng-sortable Setup (No need for bower. Bower is confusion for semis like me, too.).
This is the minimum setup to get a full sortable Array with ng-sortable, that worked for me.
Load necessary Javascripts
Load angular.js
Load ng-sortable.js (Find this in dist folder in
downloaded .zip file https://github.com/a5hik/ng-sortable)
Load your app.js
Load the as.sortable into your app
var app = angular.module('app', ['ngRoute', 'as.sortable']);
Load your AppController.js
Load necessary Stylesheets
(Find both in dist folder in downloaded .zip file https://github.com/a5hik/ng-sortable)
Load ng-sortable.css
Load ng-sortable.style.css
Create ul with necessary attributes ( data-as-sortable data-ng-model="sortableList" )
Add data-as-sortable-item to li
Insert div with data-as-sortable-item-handle into li
<!DOCTYPE html>
<html>
<head>
<title>NG-Sortable</title>
<script type="text/javascript" src="js/angular/angular.js"></script>
<script type="text/javascript" src="js/sortable/ng-sortable.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript" src="js/AppController.js"></script>
<link rel="stylesheet" type="text/css" href="css/ng-sortable.css">
<link rel="stylesheet" type="text/css" href="css/ng-sortable.style.css">
</head>
<body ng-app="app" ng-controller="AppController">
<ul data-as-sortable data-ng-model="sortableList">
<li ng-repeat="item in sortableList" data-as-sortable-item>
<div data-as-sortable-item-handle>
index: {{$index}} | id: {{item.id}} | title: {{item.title}}
</div>
</li>
</ul>
</body>
</html>
// app.js (Your file)
var app = angular.module('app', ['ngRoute', 'as.sortable']);
// AppController.js (Your file)
app.controller('AppController', [
'$scope',
function ( $scope) {
$scope.sortableList = [
{
id : "id-000",
title : "item 000"
},
{
id : "id-001",
title : "item 001"
},
{
id : "id-002",
title : "item 002"
}
];
}
]);
It would help if we knew what you mean by "setting it up" (whether you mean actually adding it to the project, or how to use it). It would also help if we knew what stack, if any, you were installing this on.
To Install
The install instructions are under the "Usage" section of their Git page.
Run bower install ng-sortable or bower install ng-sortable -save if you're using yeoman
Add the paths to ng-sortable.min.js,ng-sortable.min.css, and ng-sortable.style.min.css to your project, where you add these is dependent on what stack you're using.
Add ui.sortable as a dependency to your app or module. Again, where this goes is dependent on your stack.
To Use
<ul data-as-sortable data-ng-model="array">
<li ng-repeat="item in array" data-as-sortable-item>
<div data-as-sortable-item-handle>
{{item.data}}
</div>
</li>
</ul>
Where "array" is the array of items you're sorting.
This will work out of the box, but if you need custom logic, change data-as-sortable to data-as-sortable="CustomLogic" Where "CustomLogic" is a method in your controller that overrides the default behavior. For more details on how to add custom logic check their Git page under the section "Callbacks" and "Usage".
I just upload a simple example of this awesome library. I have two divs side by side, you can drag divs from one to the other. I'm using static data. Please check it out.
https://github.com/moytho/DragAndDropAngularJS/tree/master/DragAndDrop or as you asked for you can check it out here https://plnkr.co/SRN4u7
<body ng-controller="dragDropController">
<h1>Example</h1>
<div class="container">
<div id="row" class="row">
<div id="assignedEmployees" class="col-lg-5" style="border: 5px solid red;">
<div class="card" as-sortable="sortableOptions" data-ng-model="data.projects">
<div ng-repeat="project in data.projects" as-sortable-item>
<a title="Add card to column" ng-click="setDate(project)">
<i class="glyphicon glyphicon-plus"></i>
</a>
<div as-sortable-item-handle>{{project.FirstName}}</div>
</div>
</div>
</div>
<div id="freeEmployees" class="col-lg-5" style="background-color:lightgray;border:5px dashed gray;">
<div class="card" as-sortable="sortableOptions" data-ng-model="data.employees">
<div ng-repeat="employee in data.employees" as-sortable-item>
<div as-sortable-item-handle>{{employee.FirstName}}</div>
</div>
</div>
</div>
</div>
</div>

Angular ng-repeat, Jquery fail

So I am using ng-repeat to repeat some divs which show images out of my JSON file. What I want to do is that when I click on that image (whether its desktop or mobile) the image will scale. Now my problem is that when I want to create a click event on my image tag (which is inside that div that holds the ng-repeat), he doesn't do anything. He cant see the click.
I red something on the internet about issues with jquery and angular, but for me as a beginner its hard to understand what I have to do to make it work how I pleased. I just want to be able to put a jquery function on a image tag inside the ng-repeated divs, so I can manipulate the css from there.
I have a piece of the code posted below here, maybe I have to add something to my controller? I dont know, I am clueless at the moment. :-)
<section class="words">
<div class="colored-sidebar"></div>
<!-- content -->
<div class="previous-button"></div>
<div class="word-container" ng-controller="imageController as imageCtrl">
<h1><span>noun</span>words</h1>
<div class="category-body">
<p><span>noun</span>travel</p><hr>
<div class="category-section" ng-repeat="icon in imageCtrl.imageList.travel">
<!-- <div class="category-image" ng-include="icon.src"></div> -->
<div class="category-image">
<img src="{{icon.src}}" />
</div>
</div>
</div>
</section>
The angular file
(function() {
app.controller('imageController', function(){
this.imageList = imageJson;
});
var imageJson = {
//ALOT OF JSON DATA HERE//
};
})();
I hope this piece of code would be enough to help me :-)
Any tips are welcome, I love to learn this language better and also understand it better.
Thanks!
jQuery is not suitable here, because by the time you run your jQuery code inside jQuery.ready(), the elements in "category-image" class are not created yet.
For solution of your problem you can use two methods:
1) Use the "ng-click", as proposed before. You can also pass "$index" to function inside ng-click. This way you will know index of icon in imageList.travel that was clicked. But this way you will have no information about dom element.
2) Create a directive. The main difference between directives and controllers is that directive have information about dom object. You can treat element as typical jQuery object
JS:
app.directive('imageClick', [function () {
return {
link: function (scope, element, attr) {
element.on("click", function(e){
//do some stuff here
})
}
}
}]);
HTML
<section class="words">
<div class="colored-sidebar"></div>
<!-- content -->
<div class="previous-button"></div>
<div class="word-container" ng-controller="imageController as imageCtrl">
<h1><span>noun</span>words</h1>
<div class="category-body">
<p><span>noun</span>travel</p><hr>
<div class="category-section" ng-repeat="icon in imageCtrl.imageList.travel">
<!-- <div class="category-image" ng-include="icon.src"></div> -->
<div class="category-image">
<img image-click src="{{icon.src}}" />
</div>
</div>
</div>
</section>

Angular template within template

Lets see if I can describe my setup here...
I'm designing an angular app, as of now everything is all one page. Basically, when the user clicks a button, the controller sets which
"<ng-include>"
tag is visible. So my html looks something like this.
<html ng-app= "myApp">
<head>
<!-- header stuff -->
<!-- all the includes and everything -->
</head>
<body>
<div>
<!-- page nav bar, its a lot of html but it works -->
</div>
<!-- content area -->
<div ng-show= "showHome">
<ng-include= "home.html">
</div>
<div ng-show= "showProfile">
<ng-include= "profile.html">
</div>
<!-- etc... -->
</body>
</html>
And then in my controller, I'm just setting the proper "showHome", "showProfile", etc... as appropriate. My question is, this seems like a terrible way to scale, and this is my first attempt at an app like this.
So to reiterate. I want to give the user the appearance of a single page app, while swapping in html templates. Any ideas? Multiple pages would be ok, but I want to keep the same navbar at the top of every page.
I'd use ui-router instead.
It is a popular alternative for ngRoute and supports nested templates really well.

AngularJS ui router - not showing nested partials views

I have an AngularJs app with start up page as index.html, by default the projects view will be displayed and on top of the page I am showing a icon to show the todo items (for the logged-in user) which I am using bootstrap's data-toggle dropdown. The issue is whenever I click the todo link the partial view (todo.html) is not showing. BTW, I am new to the angular world so please forgive me if there is anything silly. Please see the code below:
Index.html
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head></head>
<body>
<a data-toggle="dropdown" class="dropdown-toggle" ui-sref=".todo">
<i class="icon-tasks"></i>
<span class="badge badge-grey">4</span>
</a>
<div ng-view></div>
</body>
app.js
// For any unmatched url, redirect to /projects
$urlRouterProvider.otherwise("/projects");
//
// Now set up the states
$stateProvider
.state('projects', {
url: "/projects",
templateUrl: "/app/views/projects/projects.html",
controller: "projectController"
})
.state('projects.todo', {
url: "/todo",
templateUrl: "/app/views/todo/todo.html"
});
First of all replace ng-view with ui-view in the root template, cause it seems you want to use ui-router instead of ng-router.
Wrap the content of your template files with div of ui-view as a parent element.
/app/views/projects/projects.html
/app/views/todo/todo.html
<div ui-view>
... previously defined content ...
</div>
Let's say your view was
<div class="container">
<div class="page-header">
<h1>Title: {{title}}</h1>
</div>
</div
you need to add ui-view to the div
<div class="container" ui-view>
<div class="page-header">
<h1>Title: {{title}}</h1>
</div>
</div
or wrap your view with div containing ui-view descriptor in case your vie contains several tags.
I cannot show you an example since you did not provide content of view files.
/app/views/projects/projects.html
/app/views/todo/todo.html
The issue is that after fist template applying angular does not see the place to put new template anymore.
ui-router isn't really supposed to be used in this way. To integrate bootstrap with angular you want to look at UI Bootstrap - http://angular-ui.github.io/bootstrap/
Then to achieve your drop down, look at their basic examples. If you want to use separate view files to define your drop down content, you can use <div ng-include="'mycontent.html'"></div>.
ui-router is useful if you have a complex view hierarchy, where you are for example, looking for dynamic loading of children, while keeping parent states static.
In ui-router you defined all of this in the $stateProvider, so there you should define that you have a view that has another view belonging to it, example:
<!-- In index.html the main view that will have all the page views-->
<div id="main" ui-view="main"></div>
<!-- In todo.html with a partial with the dropdown code in dropdown.html -->
<h1> This is a nice todo drop down </h1>
<div id="todoDropDown" ui-view="todoDropDown"></div>
//In your app file
.state('projects.todo', {
url: '/todo',
views: {
'main#': {
templateUrl: '/app/views/todo/todo.html',
controller: 'TodoCtrl'
},
'todoDropDown#projects.todo': {
templateUrl: '/app/views/partials/dropdown.html'
}
}
})
"todoDropDown#projects.todo" This does the magic, it tells that this view has another view inside. And you can add controller to it and all other options you have in ui-router. In this way you can break up as much as possible reusable parts.

Categories