Angularjs - NgView not working - javascript

Here is the basic setup, which has a default noemployee.html partial: as the ng-view
Index.html content:
<div id="container" ng-controller="EmployeeCtrl">
<!-- Side Menu -->
<span id="smenuSpan">
<ul id="thumbList">
<li ng-repeat="employee in employees | filter:categories">
<img class="smallImage" ng-src="content/app/images/{{employee.image}}" alt="{{employee.description}}">
</li>
</ul>
</span>
<!-- Content -->
<span id="contentSpan">
<div ng-view></div>
</span>
</div>
My Route Provider:
var EmployeeModule = angular.module('EmployeeModule', [], function($routeProvider, $locationProvider) {
$routeProvider.when('/', { templateUrl: 'content/app/partials/noemployee.html', controller: EmployeeModule.EmployeeCtrl });
$routeProvider.when('Employee/:id', { templateUrl: 'content/app/partials/employee.html', controller: EmployeeModule.EmployeeCtrl });
$routeProvider.otherwise({ redirectTo: '/' });
$locationProvider.html5Mode(true);
My Controller:
function EmployeeCtrl($scope, $http, $routeParams, $timeout) {
$scope.employees = [
{ "id": 1, "category": "ones", "image": "person1.jpg", "description": "person 1 description", name:"Jane Smith" },
{ "id": 2, "category": "twos", "image": "person2.jpg", "description": "person 2 description", name: "Mark Sharp" },
{ "id": 3, "category": "threes", "image": "person3.jpg", "description": "person 3 description", name: "Kenny Suave" },
{ "id": 4, "category": "fours", "image": "person4.jpg", "description": "person 4 description", name: "Betty Charmer" },
{ "id": 5, "category": "fives", "image": "person5.jpg", "description": "person 5 description", name: "John Boss" }
];
$scope.employeesCategories = [];
$scope.currentEmployee = {};
$scope.params = $routeParams;
$scope.handleEmployeesLoaded = function (data, status) {
//$scope.images = data;
// Set the current image to the first image in images
$scope.currentEmployee = _.first($scope.employees);
// Create a unique array based on the category property in the images objects
$scope.employeeCategories = _.uniq(_.pluck($scope.employees, 'category'));
}
$scope.fetch = function () {
$http.get($scope.url).success($scope.handleEmployeesLoaded);
};
$scope.setCurrentEmployee = function (employee) {
$scope.currentEmployee = employee;
};
// Defer fetch for 1 second to give everything an opportunity layout
$timeout($scope.fetch, 1000);
}
Observations:
At present, if I click on any employee, no 'Employee/??' is added to the address bar path [ which isn't a crime to me], however, the main content div does not change the partial to the employee.html.
If I comment out "$locationProvider.html5Mode(true);", the default localhost is now "http://localhost:31219/#/" and when I click on any employee the address bar shows 'http://localhost:31219/Employee/1', and the page is navigated away to a 404 error page.
I know I am bastardizing something here that the solution is so simple it escapes me.
Goals:
I really would like to avoid hash tags in my address bar.
It would be nice but no req that the employee/id not show up in the address bar but I suspect the partial cannot change w/o it. and, naturally
I want the partial to change to the 'employee.html" page when an employee is clicked.
Does anyone see where I am going wrong with this code?
Thanks in Advance!

Solution:
I needed to put '#/' in the img href --> href="#/Employee/{{employee.id}}"
Comment out
'$locationProvider.html5Mode(true);'
As a side note, I sure wish I knew how to get this to work w/o those pesky hash tags. Any ideas anyone?
In order to use html5mode, your server has to serve up the main app index file for otherwise invalid routes.
So, for example, if your server side code handles CRUD operations on paths like: /api/employees, /api/employees/:id, etc...
and it serves up static content, images, html, css, js, etc.
For any other request, that would otherwise be a 404, it should, instead of responding with a 404, respond with a 200 code, and serve up the index.html file.
This way any non static and non server side route gets handled by the angular app.
This is mentioned in the Angular guide on this page: http://docs.angularjs.org/guide/dev_guide.services.$location
Note the 'server side' comment at the end:
Html link rewriting
When you use HTML5 history API mode, you will need
different links in different browsers, but all you have to do is
specify regular URL links, such as: link
When a user clicks on this link:
In a legacy browser, the URL changes to /index.html#!/some?foo=bar
In a modern browser, the URL changes to /some?foo=bar In cases like the
following, links are not rewritten; instead, the browser will perform
a full page reload to the original link.
Links that contain target element
Example: link
Absolute links that go to a different domain
Example: link
Links starting with '/' that lead to a different base path when base is defined
Example: link
Server side
Using this mode requires URL rewriting on server side, basically you have to rewrite
all your links to entry point of your application (e.g. index.html)

This was the problem:
<img class="smallImage" ng-src="content/app/images/{{employee.image}}" alt="{{employee.description}}">
Solution:
I needed to put '#/' in the img href --> href="#/Employee/{{employee.id}}"
Comment out '$locationProvider.html5Mode(true);'
As a side note, I sure wish I knew how to get this to work w/o those pesky hash tags. Any ideas anyone?

Related

How to load JSON array to translate AngularJS webpage with Angular-Translate

I am still learning AngularJS heavily so pardon all my bad quality code/lack of knowledge.
What I want to do
I want to translate my webpage into 2 languages. It currently works when I translate static content using Angular-Translate in the index.html. Like this
function translateConfiguration($translateProvider) {
$translateProvider.useSanitizeValueStrategy(null);
$translateProvider.useStaticFilesLoader({
files: [{
prefix: '../JSON/locale-',
suffix: '.json'
}]
});
$translateProvider.preferredLanguage('en');
$translateProvider.fallbackLanguage('en');
};
I load my simple JSON files for EN and RU locales, structured like this
{
"HEADING" : "Lorem",
"TEXT" : "Ipsum"
}
Then I access the variables through Angular-translate directive
<h1 class="z-logo header-text md-display-1" translate="HEADING">
</h1>
All works as it should.
I want to be able to do the same with my custom directives and ng-repeat.
The issue
I have multiple custom directives in my AngularJS website. For instance
<about-card flex="33" flex-xs="100" flex-sm="100" class="center-content" ng-repeat="data in aboutCardCtrl.info">
</about-card>
Here is the template code that loads through the custom directive and retrieves information from the JSON file
<md-card class="card-bg card-height">
<md-card-title layout="column" class="about-card">
<md-card-title-media class="center-elements">
<img class="md-media-lg" ng-src="{{data.image}}" alt="{{data.imageAlt}}"/>
</md-card-title-media>
<md-card-title-text>
<div class="md-headline card-title-padding">{{data.heading}}</div>
</md-card-title-text>
</md-card-title>
<md-card-content>
{{data.content | translate}}
</md-card-content>
</md-card>
Here is the directive
(function() {
'use strict'
angular
.module('webApp')
.directive('aboutCard', aboutCard);
function aboutCard() {
return {
restrict: 'EA',
priority: 1001,
templateUrl: '../TEMPLATES/about.html',
controller: 'aboutCardController',
controllerAs: 'aboutCardCtrl'
};
};
})();
Here is the controller
(function() {
'use strict'
angular
.module('webApp')
.controller('aboutCardController', aboutCardController);
aboutCardController.$inject = ['JsonData', '$translate'];
function aboutCardController(JsonData, $translate) {
var vm = this;
vm.pathToJson = '../JSON/about-en.json';
vm.info = [];
JsonData.all(vm.pathToJson).then(function(response) {
vm.info = response.data.information;
});
};
})();
Here is the JSON file
{
"information": [{
"heading": "Reliability",
"content": "Our partners have been working on the market for over 10 years",
"image": "../IMG/shield.svg",
"imageAlt": "Reliability Image"
}, {
"heading": "Professionalism",
"content": "We are ready to provide profesional opinion for our clients to ensure the right choice",
"image": "../IMG/people.svg",
"imageAlt": "Professionalism Image"
}, {
"heading": "Development",
"content": "Organization of educational programs in collaboration with our partners",
"image": "../IMG/cogwheel.svg",
"imageAlt": "Development Image"
}]
}
Here I suppose I lack the brainpower to understand how I can load my JSON files and switch between them in the custom directive with ng-repeat. Since The format of the JSON is different.
I've been going through Angular-Translate wiki pages, but all examples feature only index.html and main app.js files and I hardly seem to be able to find/understand examples found in google search like these
https://technpol.wordpress.com/2013/11/02/adding-translation-using-angular-translate-to-an-angularjs-app/
https://github.com/angular-translate/angular-translate/issues/1154
You can use dynamic loader instead of static.
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: 'JSON/{part}/{lang}.json'
});
And then load JSON that you need like this:
$translatePartialLoader.addPart('about');
Language prefix will be automatically add to the path.

Why isn't list of elements showing up?

I am working on an AngularJS tutorial
This tutorial covers the ng-repeat directive, an AngularJS directive used repeating data.
To show an example of ng-repeat, The author enters periodic table elements in a JSON format, covering element's name, element #, etc into controller logic($scope)
To display the elements(code below), the author simply used the directive with a html un-ordered list
<ul>
<li data-ng-repeat="element in periodic.elements">{{element.name}} </li>
</ul>
I tried doing the same JsFiddle but the list of elements isn't showing up, only {{element.name}}
At first I thought this was an AngularJS syntax issue but I checked over the scope attribute, if the controller names match, etc.... I made sure to enable the AngularJS option in JsFiddle as well.
Does anyone know what the issue is or why this list isn't showing up?
You forget completing controller sytax '});' at the end of the code.
'use strict';
var chemistryApp = angular.module('chemistryApp', []);
chemistryApp.controller(
'chemistryController',
function chemistryController($scope) {
$scope.periodic = {elements: [
{
"atomicNumber": 1,
"name": "Hydrogen",
"atomicWeight": 1.00794,
"phase": "Gas",
"ionization": 13.5984,
"melting": -259.15,
"boiling": -252.87
},
{
"atomicNumber": 2,
"name": "Helium",
"atomicWeight": 4.002602,
"phase": "Gas",
"ionization": 24.5874,
"melting": 0,
"boiling": -268.93
},
{
"atomicNumber": 3,
"name": "Lithium",
"atomicWeight": 6.941,
"phase": "Solid",
"ionization": 5.3917,
"melting": 180.54,
"boiling": 1342
}
]
};
});
Working Fiddle

fetch and load image in angularjs

I'm fetching post data from facebook on my website, but the json data does not contain full size image. So I have to fetch image from other source.
post data example:
{
"data": [{
"id": "1",
"from": {
"category": "Company",
"name": "Example",
"id": "12"
},
{
"id": "2",
"from": {
"category": "Company",
"name": "Example1",
"id": "112"
}
]}
so, the facebook post should have images and it fetches from different source. Each time I want to get image of a post, I will fetch data based on post id
{
full_picture: 'http://linkhere'
}
my page is using angularjs to display post content.
<div ng-repeat="post in postsList">
<div>{{post.id}}</div>
<img src="???" />
</div>
Basically, I will use post id to get image url, but I dont know how to call the function to get image url based on the post id. Do we have the way in angularjs that passing something like
<image ng-src="funcName({{post.id}})" />
I'm totally new with angularjs framework, so I appreciate all ideas
You don't need the expression to call your function with post.id. You do however, need the function inside an expression for ng-src.
<image ng-src="{{funcName(post.id)}}" />
var app = angular.module('app', []);
app.controller('myController', function($scope) {
$scope.posts = [{id: 1}, {id: 2}];
$scope.funcName = function(id) {
return IMAGES[id];
};
});
var IMAGES = {
1: 'BoCw8.png',
2: 'Ed3JT.png'
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app='app' ng-controller='myController'>
<div ng-repeat="post in posts">
<image ng-src="http://i.stack.imgur.com/{{funcName(post.id)}}" />
</div>
</div>
Basically, yes. Check the docs for ng-src
<img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />

Drill Down into JSON Object in Angular

I'm trying to figure out the best way to take a json object which I'm storing as a scope, and filter/query it to display specific data from within it.
For example:
$scope.myBook = {"bookName": "Whatever",
"pages": [
{"pageid": 1, "pageBody": "html content for the page", "pageTitle": "Page 1"},
{"pageid": 2, "pageBody": "html content for the page", "pageTitle": "Page 2"},
{"pageid": 3, "pageBody": "html content for the page", "pageTitle": "Page 3"},
]
}
How would I go about grabbing the object for pageid:2 ?
You can use this approach:
template:
<div ng-repeat="page in myBook.pages | filter:pageMatch(pageid)">
{{ page.pageBody }}
</div>
scope:
$scope.pageMatch = function(pageid) {
return function(page) {
return page.pageid === pageid;
};
};
Set pageid to needed value in filter:pageMatch(pageid) to display necessary page content.
function getPage (id) {
angular.forEach($scope.myBook.pages, function (page, pageIndex) {
if (page.pageId == id) {
console.log("Do something here.");
return page;
}
});
}
Otherwise . . .
$scope.myBook.pages[1];
I ended up asking the AngularJS IRC - And one of the guys put this plunker together with exactly what I was looking for.
Plnkr Example
Props to https://github.com/robwormald for the answer.
/* See PLNKR Link Above for the answer */

with jsRender, how do you pull a specific item from array using something other than ordinal position?

I'm trying to render some JSON data using jsRender. Below is my sample JSON data
"PageContentList": [
{
"ContentId": 51,
"Title": "60 seconds with Rick",
"ContentMediaTypeList": [
{
"MimeType": "image/png",
"MediaTypeName": "Image",
"Path": "http://local.admin.solutiaconsulting.com/uploads/4a906d8e-983a-4b54-a627-0e8d48145620.png"
},
{
"MimeType": "video/webm",
"MediaTypeName": "Video",
"Path": "http://local.admin.solutiaconsulting.com/uploads/3a6c56c3-0ef9-4f57-9c84-9caa48a09044.webm"
}
]
}
]
I want to pull the different images based on MediaTypeName instead of the ordinal position. I know I can do this:
{{:ContentMediaTypeList[1].Path}}
and I know I can do this:
{{for ContentMediaTypeList}}
{{if MediaTypeName == 'Video'}}
{{:Path}}
{{/if}}
{{/for}}
But the second approach seems cumbersome and wasteful. Is what I want to do even possible? Thanks for your help.
Thank you Charlie for your reply. I ended up changing the structure of my JSON to this:
"PageContentList": [
{
"ContentId": 44,
"Title": "Company Name",
"Gallery": {
"Images": [
{
"Path": "http://local.admin.solutiaconsulting.com/uploads/9b577ef7-ea8a-42a1-b967-89debbc634c0.jpg",
"MimeType": "image/jpeg",
"ImageWidth": 0,
"ImageHeight": 0,
"AltText": null
}
],
"Videos": [ ]
}
},
....
]
Then for my template:
{{for PageContentList}}
<video id="whatIsSolutiaVideo" class="video-js vjs-default-skin" controls width="{{:Gallery.Images[0].ImageWidth}}" height="{{:Gallery.Images[0].ImageHeight}}" poster={{:Gallery.Images[0].Path}}" preload="auto">
{{for Gallery.Videos}}
<source type="{{:MimeType}}" src="{{:Path}}">
{{/for}}
</video>
{{/for}}
I know each JSON data will have a section for Images, Videos, etc. Now it becomes a data entry issue. If the data entry person did their job right, then there will be data. The approach I moved to ensures the correct data structure. Thanks for forcing me to think through this.
There is no easy way to do it, because you are not supposed to perform that kind of logic in the view. Place your filter in the model or a controller before you render it.
The one exception I can think of in this case is if you would like to limit the number of items to display. That might or might not be a suitable task for the view depending on the situation.
Examples:
Keep the logic of a limit out of the view:
- List of Question on Stack Overflow with paging (limit, offset, sorting)
Enforce a limit in the view:
- A list of attached images for each question. Your mobile view only have room to show one per question. The view suitable for desktop have room for three.
How to structure your application and where to place your logic is a debate with many opinions though. This style of separation is what I've been taught from experience and peers, but I am sure that there are many out there with different idéas.
Here's a simple way to filter your data using underscore.js.
var videoContent = _.filter(contentMediaTypeList, function(mediaType) {
return mediaType.mediaTypeName == "video";
});
Working JSFiddle: http://jsfiddle.net/n98yW/
Or create a closure out of it for reusability
var mediaTypeFilter = function(mediaTypeName) {
return function(contentMediaTypeList) {
return _.filter(contentMediaTypeList, function(currMediaType) {
return currMediaType.MediaTypeName == mediaTypeName;
});
}
};
And use it like this
var videoFilter = mediaTypeFilter("video");
var videoContent = videoFilter(contentMediaTypeList);
Here's another JSFiddle for this solution using a closure: http://jsfiddle.net/GA55g/2/

Categories

Resources