Angular 1.5 Component Example - angularjs-components

I am fairly experienced using Angular pre-1.5, but I am currently starting to develop a web application based on 1.5 components. After much troubleshooting, I still can't seem to get a basic template working - can I get another set of eyes to please tell me what is wrong with the following simple menu component? I appreciate any assistance that may be offered.
var appMenuTemplate = "
<nav class='menu'>
<ul>
<li ng-repeat='item in menuCtrl.menuItems'>
{{ item }}
</li>
</ul>
</nav>
";
var appMenuController = function() {
var self = this;
self.menuItems = [
'home',
'about',
'portfolio',
'experience'
];
};
angular
.module('exampleApp', [])
.component('appMenu', {
template: appMenuTemplate,
controller: appMenuController,
controllerAs: 'menuCtrl'
});
https://jsfiddle.net/dzaslow/ej8r3vyo/1/

Here's how to do it. I learned how to use components mainly from reading todd motto's posts. You should probably also use templateUrl rather than template.
(function() {
'use strict';
angular
.module('exampleApp', [])
.component('appMenu', {
template: "<nav class='menu'> \
<ul> \
<li ng-repeat='item in vm.menuItems'> \
{{ item }} \
</li> \
</ul> \
</nav>",
controller: AppMenuController,
controllerAs: 'vm'
});
function AppMenuController() {
var vm = this;
vm.menuItems = [
'home',
'about',
'portfolio',
'experience'
];
}
AppMenuController.$inject = [];
})();
.menu > ul > li {
display: inline;
margin-right: 1em;
}
<!DOCTYPE html>
<html ng-app='exampleApp'>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>
</head>
<body>
<app-menu></app-menu>
</body>
</html>

Related

How do I mouseover

I am doing a course on DOM Event manipulation.
I am trying to make a todolist where the color of the li changes when I hover on it.
My problem is that the color changes when I click on the element and not when I hover on it. Thank you in advance.
I have the following js:
var lis = document.querySelectorAll("li");
for(var i = 0; i < lis.length; i++){
lis[i].addEventListener("mouseover", function(){
this.classList.add("selected");
});
lis[i].addEventListener("mouseout", function(){
this.classList.remove("selected");
});
lis[i].addEventListener("click", function(){
this.classList.toggle("done");
})
}
.done {
text-decoration: line-through;
opacity: 0.5;
}
.selected {
color: green;
}
<!DOCTYPE html>
<html>
<head>
<title>Todo List Demo</title>
<link rel="stylesheet" type="text/css" href="todos.css">
</head>
<body>
<ul>
<li>Wash cat</li>
<li>Feed Cat</li>
<li>Feed cat to dog</li>
</ul>
<script type="text/javascript" src="todos.js"></script>
</body>
</html>
Html part:
<ul>
<li onmouseenter="enter(0)" onmouseout="out(0)">Milk</li>
<li onmouseenter="enter(1)" onmouseout="out(1)">Eggs</li>
<li onmouseenter="enter(2)" onmouseout="out(2)">Fruits</li>
</ul>
Js:
function enter(x) {
document.getElementsByTagName('li')[x].style.color = "red"
}
function out(y) {
document.getElementsByTagName('li')[y].style.color = "black"
}
By The way I just tested the code and It worked! :)

Scala.js webloaded js libraries not present?

I setup a project using scala.js.
At the web part (playframework) I added a static library bxslider.
With scala.js I add a complete new slider (div, ul and li). Without scala.js all works fine, with scala.js the inserted code is not going to be a slider.
I tried to pass a script part with bxSlider() to the correct id. No effect. I get the error bxSlider() is no function.
It seemed to me, that their is no access to bxSlider. Where is the error?
object WidgetSingleArticleSlider {
def articleEntry(x: SharedArticle, addToCartText: String) = {
li(
`class`:="wgsp-item",
a(
href:="#",
figure(
img(src:=x.articleDescription.pictureSeq.headOption.getOrElse(Pictures.emptyPath))
)
),
p(
`class`:="wgsp-title",
a(
href:="#",
x.articleDescription.title
)
),
p(
`class`:="wgsp-price",
(if(x.price.articlePrice(1).specialSubTotal.isDefined)
x.price.articlePrice(1).specialSubTotal.get.formatted("%,.2f ")
else x.price.articlePrice(1).subTotal.formatted("%,.2f ")) + x.price.articlePrice(1).currency
),
div(
`class`:="row no-gutter",
div(
`class`:="col-xs-12 text-center",
a(
`class`:="btn btn-third-col",
href:="#",
addToCartText
),
div(`class`:="gap-30")
)
)
)
}
def toHtml(title: String, articleSeq: Seq[SharedArticle], addToCartText: String) = {
div(
`class`:="widget wg-specials store-alt box-with-pager mobile-collapse",
h3(
`class`:="wg-title mobile-collapse-header store-alt",
title
),
div(
`class`:="wg-body mobile-collapse-body",
ul(
id := "tium",
`class`:="vertical-bx-1",
articleSeq.map(e => articleEntry(e,addToCartText))
)
)
)
}
}
In main.scala.html this is added at the end:
<script src="#routes.Assets.versioned("js/jquery-1.11.0.min.js")"></script>
<script src="#routes.Assets.versioned("js/jquery-ui-1.10.4.custom.min.js")"></script>
#*<script src="#routes.Assets.versioned("plugins/jquery.bxslider.min.js")"></script>*#
<script src="#routes.WebJarAssets.at(webJarAssets.locate("js/jquery.bxslider.js"))"></script>
<script src="#routes.Assets.versioned("js/bootstrap.min.js")"></script>
<script src="#routes.Assets.versioned("js/jquery-accessibleMegaMenu.js")"></script>
<script src="#routes.Assets.versioned("js/jquery.validationEngine.js")"></script>
<script src="#routes.Assets.versioned("js/jquery.validationEngine-en.js")"></script>
<script src="#routes.Assets.versioned("js/fastclick.js")"></script> <!-- Eliminating the 300ms click delay on mobile browsers -->
<script src="#routes.Assets.versioned("js/plugins.js")"></script>
<script src="#routes.Assets.versioned("js/scripts.js")"></script>
#scalajs.html.scripts("client", routes.Assets.versioned(_).toString, name => getClass.getResource(s"/public/$name") != null)
After this their is a request (which works) to scala.js which add the code above to the html structur at main.scala.html.
Now the adding sequence of my scala.js
val child = place.appendChild(Waiting.spinner.render)
Ajax.get(url(s"list/article/random?size=$size"),withCredentials = true).map{ xhr =>
place.removeChild(child)
val articleSeq = upickle.default.read[Seq[SharedArticle]](xhr.responseText)
val box = WidgetSingleArticleSlider.toHtml( title, articleSeq, addToCartText )
place.appendChild( box.render )
}
The problem is, that this added code is not transformed to a bxSlider. Also I try to restart it again as a bxSlider added as a script at WidgetSingleArticleSlider with:
$('.vertical-bx-1').bxSlider({
minSlides: 3,
slideMargin:0,
nextText: '<i class="arrow_carrot-right"></i>',
prevText: '<i class="arrow_carrot-left"></i>',
pager: false,
}));
The result is still only html. Asking for the loaded plugin results in undefined.
This is the code which was added after call:
<div class="widget wg-specials store-alt box-with-pager mobile-collapse"><h3
class="wg-title mobile-collapse-header store-alt">specials</h3>
<div class="wg-body mobile-collapse-body">
<ul id="tium" class="vertical-bx-1">
<li class="wgsp-item"><a href="#">
<figure><img src="/thumbnail/width/200/nothing"></figure>
</a>
<p class="wgsp-title">Wiesenkerbel Saatgut</p>
<p class="wgsp-price">2.34 EUR</p>
<div class="row no-gutter">
<div class="col-xs-12 text-center"><a class="btn btn-third-col" href="#">addToCart</a>
<div class="gap-30"></div>
</div>
</div>
</li>
<li class="wgsp-item"><a href="#">
<figure><img src="/thumbnail/width/200/nothing"></figure>
</a>
<p class="wgsp-title">Vogelmiere Saatgut</p>
<p class="wgsp-price">2.34 EUR</p>
<div class="row no-gutter">
<div class="col-xs-12 text-center"><a class="btn btn-third-col" href="#">addToCart</a>
<div class="gap-30"></div>
</div>
</div>
</li>
</ul>
</div>
<script>
jQuery('#tium').bxSlider();
if (window.jQuery === undefined) window.$ = window.jQuery = jQuery;
$(document).ready(function () {
$('.vertical-bx-1').bxSlider().reloadSlider();
$('#tium').bxSlider().reloadSlider();
$('.vertical-bx').bxSlider({
minSlides: 3,
slideMargin: 0,
nextText: '<i class="arrow_carrot-right"></i>',
prevText: '<i class="arrow_carrot-left"></i>',
pager: false
});
});
</script>
</div>
Solution found. No problem with scala.js it was jquery.
https://github.com/stevenwanderski/bxslider-4/issues/605
var j = jQuery.noConflict();
I added this line to my code and all worked fine.

Angular states and Browser back button

I am trying to adapt the following code:
Plunker
Here is the code:
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<title>AngularJS: UI-Router Quick Start</title>
<!-- Bootstrap CSS -->
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter- bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="container">
<div class="navbar">
<div class="navbar-inner">
<a class="brand" ui-sref="index">Quick Start</a>
<ul class="nav">
<li><a ui-sref="index">Home</a></li>
<li><a ui-sref="route1">Route 1</a></li>
<li><a ui-sref="route2">Route 2</a></li>
</ul>
</div>
</div>
<div class="row">
<div class="span6">
<div class="well" ui-view="LeftMenu"></div>
</div>
<div class="span6">
<div class="well" ui-view="Content"></div>
</div>
</div>
<!-- Angular -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js"></script>
<!-- UI-Router -->
<script src="//angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<!-- App Script -->
<script>
var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider){
$stateProvider
.state('index', {
url: "",
views: {
"LeftMenu": {
template: '<ul><li><a ui-sref="index.LeftMenuMenu1">Index-Left Menu1</a></li><li><a ui-sref="index.LeftMenuMenu2">Index-Left Menu2</a></li><li><a ui-sref="index.LeftMenuMenu3">Index-Left Menu3</a></li></ul>'
},
"Content": {
template: "<div ui-view></div>"
}
}
})
.state('index.LeftMenuMenu1', {
template: "LeftMenu.Menu1 selected"
})
.state('index.LeftMenuMenu2', {
template: "LeftMenu.Menu2 selected"
})
.state('index.LeftMenuMenu3', {
template: "LeftMenu.Menu3 selected"
})
.state('route1', {
url: "/route1",
views: {
"LeftMenu": {
template: '<ul><li><a ui-sref="Route1.Menu1">Route1-Left Menu1</a></li><li><a ui-sref="Route1.Menu2">Route1-Left Menu2</a></li><li><a ui-sref="Route1.Menu3">Route1-Left Menu3</a></li></ul>'
},
"viewB": {
template: "route1.viewB"
}
}
})
.state('route2', {
url: "/route2",
views: {
"LeftMenu": {
template:'<ul><li>Route2-Left Menu1</li><li>Route2-Left Menu2</li><li>Route2-Left Menu3</li></ul>'
},
"viewB": {
template: "route2.viewB"
}
}
})
});
</script>
It definitely works fine. What I'd like to have is when I click on Back button it doesn't go back to the previous vertical state if they were selected, but instead goes back to the previous state on the horizontal menu.
Is that possible?
Thanks

angularjs socials share buttons troubles the display is only in one page

I'm going mad with a simple embedded of social buttons.
Put it in this way I've got two states home and blog
with this code
home
<div id="socials-bar" class=" clearfix">
<ul class="pull-right">
<li>
<div class="fb-like" data-href="http://mydomain.com" data-layout="standard" data-action="like" data-show-faces="false" data-share="true"></div>
</li>
<li>
Tweet
</li>
<li>
<div class="g-plusone" data-size="small" data-annotation="inline" data-width="120" data-href="http://mydomain.it"></div>
</li>
</ul>
</div>
//other html
<script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
</script>
<script>
window.___gcfg = {lang: 'it'};
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/platform.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
blog
<div class="clearfix">
<ul class="article-socials pull-right">
<li>
<div class="fb-like" data-href="http://mydomain.it/blog/{{article.id}}/{{article.slug}}" data-layout="standard" data-action="like" data-show-faces="false" data-share="true"></div>
</li>
<li>
Tweet
</li>
<li>
<div class="g-plusone" data-size="small" data-annotation="inline" data-width="120" data-href="http://mydomain.it/blog/{{article.id}}/{{article.slug}}"></div>
</li>
</ul>
</div>
<script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
</script>
<script>
window.___gcfg = {lang: 'it'};
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/platform.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
The problem is that the I see them only in the home
page if I get rid off of them in home I can see them in the blog state
Do you know what could be the problem ?
UPDATE: I've updated the below directives and registered them on bower with the package name 'angulike', for full details and a working demo go to http://jasonwatmore.com/post/2014/08/01/AngularJS-directives-for-social-sharing-buttons-Facebook-Like-GooglePlus-Twitter-and-Pinterest.aspx
The problem is that the social buttons only get initialized on page load by default, so in an angularjs app you need to re-initialize the buttons yourself when the view changes. I got them working by creating a directive for each, below is the code:
Google Plus Button Directive
app.directive('googlePlus', ['$window', function ($window) {
return {
restrict: 'A',
template: '<div class="g-plusone" data-size="medium"></div>',
link: function (scope, element, attrs) {
scope.$watch(function () { return !!$window.gapi; },
function (gapiIsReady) {
if (gapiIsReady) {
$window.gapi.plusone.go(element.parent()[0]);
}
});
}
};
}]);
Tweet Button Directive
app.directive('tweet', ['$window', function ($window) {
return {
restrict: 'A',
template: 'Tweet',
link: function (scope, element, attrs) {
scope.$watch(function () { return !!$window.twttr; },
function (twttrIsReady) {
if (twttrIsReady) {
$window.twttr.widgets.load(element.parent()[0]);
}
});
}
};
}]);
Facebook Like Button Directive
app.directive('fbLike', ['$window', function ($window) {
return {
restrict: 'A',
template: '<div class="fb-like" data-layout="button_count" data-action="like" data-show-faces="true" data-share="true"></div>',
link: function (scope, element, attrs) {
scope.$watch(function () { return !!$window.FB; },
function (fbIsReady) {
if (fbIsReady) {
$window.FB.XFBML.parse(element.parent()[0]);
}
});
}
};
}]);
HTML to use the directives
<div data-fb-like=""></div>
<div data-tweet=""></div>
<div data-google-plus=""></div>
If I understand, probably you should remove the script in blog state template.
Anyway, I can share how I do in my sample project:
index.html
directive for social buttons
template for
social buttons
basically in index there are scripts for social buttons available for all states

Autocomplete Not Working in DurandalJS Modal View

I am using the DurandalJS framework for my PHP web application. I am exploiting DurandalJS framework features for showing modal views.
I have a homepage, home.html which contains a link to a page called, autocomplete.html. When this link is clicked, it opens the autocomplete.html page inside a modal view (a feature provided by DurandalJS).
I am also using the jQuery-UI autocomplete feature to create an autocomplete for a textbox. When a user types anything into the textbox, he gets a list of suggestions based on the characters he enters through the keyboard.
The problem here is that the autocomplete feature works if the autocomplete.html page is run independently in the browser. However, this feature doesn't run when the page is shown in the modal i.e. by running (navigating) the project through the DurandalJS framework.
Can anyone please tell me where exactly am I going wrong? Replies at the earliest will be highly appreciated.
The source code for my project is given below. Please note that the order in which I have provided the source code is in the same order in which the DurandalJS navigation call stack is executed. The flow of my application is, index.php >>> main.js >>> shell.js >>> shell.html >>> home.js >>> home.html >>> autocomplete.js >>> autocomplete.html.
The autocomplete.js >>> autocomplete.html call stack is executed when the user clicks on the Go to Autocomplete link on the home.html page.
main.js
require.config({
paths: {
'text': 'durandal/amd/text'
}
});
define(function (require) {
var app = require('durandal/app'),
viewLocator = require('durandal/viewLocator'),
system = require('durandal/system'),
router = require('durandal/plugins/router');
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");
app.start().then(function () {
//The following statement is to help DurandalJS to find files only according to their names.
//Replace 'viewmodels' in the moduleId with 'views' to locate the view.
//Look for partial views in a 'views' folder in the root.
viewLocator.useConvention();
//configure routing
router.useConvention();
router.mapNav("pages/home");
router.mapNav("pages/autocomplete");
app.adaptToDevice();
//Show the app by setting the root view model for our application with a transition.
app.setRoot('viewmodels/shell', 'entrance');
});
});
shell.js
define(function (require) {
var router = require('durandal/plugins/router');
return {
router: router,
activate: function () {
return router.activate('pages/home');
}
};
});
shell.html
<br />
<br />
<br />
<br />
<div class="container-fluid page-host">
<!--ko compose: {
model: router.activeItem, //wiring the router
afterCompose: router.afterCompose, //wiring the router
transition:'entrance', //use the 'entrance' transition when switching views
cacheViews:true //telling composition to keep views in the dom, and reuse them (only a good idea with singleton view models)
}--><!--/ko-->
</div>
home.js
// JavaScript Document
//This file loads the respective page's ViewModel (<Page>.js) and displays the View (<page>.html)
define(function (require) {
self.app = require('durandal/app');
return {
movies: ko.observable(),
activate: function() {
var self = this;
//The following code in the function creates a modal view for the autocomplete page
self.viewAutoCompleteModal = function(AutoComplete, element) {
app.showModal("viewmodels/pages/autocomplete");
};
}
};
});
home.html
<div id="applicationHost">
<div class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<a class="brand">
<span>My application</span>
</a>
</div>
</div>
</div>
</div>
<!--The following lines of code create href links for the My Application pages and directs the DurandalJS to the respective pages. The data-bind attribute calls the view<Page>Modal functions (which create a Modal view) which is defined in the ViewModel (<Page>.js file)-->
<br />
<br />
Go to Autocomplete
autocomplete.js
// JavaScript Document
define(function (require) {
var router = require('durandal/plugins/router');
var moviesRepository = require("repositories/moviesRepository");
return {
activate: function (context) {
}
};
});
autocomplete.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<title>jQuery-UI Autocomplete Demo</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<script src="http://localhost/rockontechnologies/Scripts/Script1.10.3/jquery-1.9.1.js"></script>
<script src="http://localhost/rockontechnologies/Scripts/Script1.10.3/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<script>
$(function() {
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
$( "#tags" ).autocomplete({
source: availableTags
});
});
</script>
</head>
<body>
<div class="modal-footer">
<ul class="btn-group">
<button class="btn" data-bind="click: closeModal">Exit</button>
</ul>
</div>
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags">
</div>
</body>
</html>
For help on DurandalJS, I have referred to:
http://durandaljs.com/
For help on Autocomplete, I have referred to: [http://jqueryui.com/autocomplete/][3]
Thank you in advance.
ive answered a similar question here which will help you.
But your autocomplete.html is wrong and will not work when composed by Durandal. You need to convert that to a durandal style html page.
Add your script tags to your host page. In Hot Towel this is managed by bundles so im not entirely sure where you add these if using PHP.
Remove the HTML, SCRIPT, META etc... Just leave the pure HTML markup.
e.g:
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags">
</div>
Then in your autocomplete.js file, add an attached method or if using Durandal < 2.0.0 you add a viewAttached method.
define(function (require) {
var router = require('durandal/plugins/router');
var moviesRepository = require("repositories/moviesRepository");
return {
activate: function (context) {
},
attached: function (view) {
var $tagInput = $(view).find('#tags');
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
$tagInput.autocomplete({
source: availableTags
});
}
};
});
Let me know if you are still having issues and ill be pleased to help.