angular strap - bs-tabs not refreshing properly when ng-repeat points to new array object - angularjs

I am trying to build a tab set that would dynamically change on user action using bs-tabs angularstrap directive and ng-repeat (Say initially the tabs were a,b,c. On some user action it should change to x,y,z)
I am trying to do this by pointing the ng-repeat to a new array object on an user action say a click of a button.
Instead of the tab set getting refreshed, I am noticing a strange behavior
Ive recreated it in this plnkr, please have a look at it,
http://plnkr.co/edit/bpKDx56bieIshKaedzv6?p=preview
<!DOCTYPE html>
<html ng-app="angularjs-starter">
<head lang="en">
<meta charset="utf-8">
<title>AngularStrap - Tab directive</title>
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" rel="stylesheet">
<link href="//mgcrea.github.com/angular-strap/css/prettify.css" rel="stylesheet">
<!-- required libraries -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<script src="//mgcrea.github.com/angular-strap/js/angular-strap.js"></script>
<!-- optional libraries -->
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.0.0/moment.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fastclick/0.6.0/fastclick.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/prettify/r224/prettify.js"></script>
<link rel="stylesheet" href="style.css">
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div data-fade="1" ng-model="tabs.activeTab" bs-tabs>
<div ng-repeat="tab in tabs" data-title="{{tab.title}}"><p>{{tab.content}}</p></div>
</div>
<button type="button" class="btn btn-primary" ng-click="changeTabs()">Show different set of tabs</button>
</body>
</html>

Looking at the code it seems that the tab directive observes the active tab value and refreshes only the tab content using transclusion, whereas the tab title is only assigned initially.
I think the only way to change title dinamically is creating a new directive that creates a tab directive dinamically, initializing it with the fresh values.

Related

Open a new Site in angular

I had a Single Page Application developed in angular-js and i need to open a printside under a new url. At present, printtext.html loads its content but on the inside of the index.html. What i want is to load the content of the printtext.html alone without any Content from the index.html. Basically if i click on the link in my index.html i just want to see in the browser the text printtext. And not something like Some headertext which is curretnly the case. Is that possible or do i break the SPA rules? My Main goal is to create a Printsite where i just see the content without any header or footer information. Or should i user ng-hide for this?
I am not including the logic here, but if required will provide.
Index.html
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Myapp</title>
<script src="libs/js/angular.js"></script>
<script src="libs/js/angular-route.js"></script>
<script src="js/app.js"></script>
</head>
<body>
<h1> Some headertext </h1>
<ng-view></ng-view>
</body>
app.js
var app = angular.module('myapp', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/text', {
templateUrl: "template/text.html"
})
.when('/print', { //actually the parameter is /print/:object but i left the logic out here
templateUrl: "Print/printtext.html"
})
}])
text.html
<p> Some text </p>
<a ng-href="#!/print">Print </a> <!-- The right link would be something like #!/print/marc -->
printtext.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html ng-app="myapp">
<head><title>
Printview
</title>
<script src="../libs/js/angular.js"></script>
<script src="../libs/js/angular-route.js"></script>
<script src="../js/app.js"></script>
<body>
<p>printtext</p>
</body>
</html>
You directly use target = "_blank" in your anchor tag.
<p> Some text </p>
<a ng-href="#!/print" target="_blank">Print </a> <!-- The right link would be something like #!/print/marc -->
Otherwise, you can create a dynamically custom directive in angular.
custom directive generally uses to set target according to a dynamic condition.
<p> Some text </p>
<a ng-href="#!/print" ng-attr-target="_blank">Print </a> <!-- The right link would be something like #!/print/marc -->
<a ng-attr-target="_blank">
...
</a>
ng-attr-xyz lets you dynamically create #xyz, and if the value is undefined no attribute is created.

Why are the DOM plain html elements rendered only after my Angular APP is done loading?

I am trying to display a plain html/css loading spinner on first load in my Angular APP. The spinner code is included in my index.html.
However, the dom seems not to be rendered until my angularjs APP starts kicking in, causing a very lengthy display of a white screen until this finally happens. Is there any way to prevent that?
I would like to understand how to load my plain html/css spinner right after the css code in the head is done loading so as to improve user experience.
Test on webpagetest.org seem to confirm this diagnosis (the /settings, /introductions, /menus lines are all calls to an external API done by an AngularJS service before render):
Here is a simplified version of my build code:
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
<title ng-bind="($title || 'Home') + ' - WalktheChat'">WalktheChat</title>
<link rel="stylesheet" href="styles/lib.css">
<link rel="stylesheet" href="styles/app.css">
</head>
<body>
<div id="base-container" ng-controller="Shell as main">
<div ng-include="'app/layout/header.html'"></div>
<div id="content" ui-view ng-cloak autoscroll="true"></div>
<div ng-include="'app/layout/footer.html'"></div>
</div>
<!-- This is the spinner I would like to display on first load -->
<div ng-show="::false" class="spinner-container">
<div class="spinner sk-spinner sk-spinner-pulse"></div>
</div>
<script src="js/lib.js"></script>
<script src="js/app.js"></script>
</body>
</html>
whatever the complexity of your application,all your controllers are within the same angular application, all scopes within the same application inherits from the same root, whatever you define on the $rootScope will be available to all child scopes.
we have two ways to resolve this problem:
use $broadcast(), $emit() and $on() that facilitate event driven publisher-subscriber model for sending notifications and passing data between your controllers.(professional solution)
declare $rootScope variable and watching changement.(simple way)
It turns out the problem was coming from "render-blocking javascript", I had to add the "async" tag to my JS to fix it.
When adding async to both my lib.js and app.js, I had an issue with app.js loading before angular scripts were loaded (thus causing the APP to throw an error). In order to solve this issue, I combined my lib.js and app.js into one single file and then added the async tag.
My final build code looks like that (the magic happens on the final "script" tag):
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
<title ng-bind="($title || 'Home') + ' - WalktheChat'">WalktheChat</title>
<link rel="stylesheet" href="styles/lib.css">
<link rel="stylesheet" href="styles/app.css">
</head>
<body>
<div id="base-container" ng-controller="Shell as main">
<div ng-include="'app/layout/header.html'"></div>
<div id="content" ui-view ng-cloak autoscroll="true"></div>
<div ng-include="'app/layout/footer.html'"></div>
</div>
<!-- This is the spinner I would like to display on first load -->
<div ng-show="::false" class="spinner-container">
<div class="spinner sk-spinner sk-spinner-pulse"></div>
</div>
<!-- This app.js now also contains lib.js from my question !-->
<script src="js/app.js" async></script>
</body>
</html>

Iterating through image array using ng-repeat

I am trying to make the li's repeat for each image in the image array. Using the variable image as my identifier identifier but for some reason I am not able to loop through the array. I am making adjustments in the following line:
<li class="small-image pull-left thumbnail" ng-repeat="product in store.products.images" >
Please refer to the Plunker for the code.Here is my Plunker
I just updated head part in your HTML in plunker to
<head>
<script data-require="angular.js#1.4.0-beta.5" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
<script type="text/javascript" src="app.js"></script>
</head>
angular.min.js was faulty

Angular-strap modal shows empty

I am trying to implement angular-strap modal, I have an external template of modal but it shows as blank. Whats wrong ?
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link data-require="bootstrap-css#3.3.1" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script data-require="angular.js#1.3.13" data-semver="1.3.13" src="https://code.angularjs.org/1.3.13/angular.js"></script>
<script data-require="angularstrap#*" data-semver="2.1.2" src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.2/angular-strap.min.js"></script>
<script data-require="angularstrap#*" data-semver="2.1.2" src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.2/angular-strap.tpl.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<button class="btn btn-default" content-template="customer.tpl.html" bs-modal="modal">New Customer</button>
</body>
</html>
Here's link to Plunker
Couple of things you need to fix:
The first is to replace content-template with data-template, and the second is that if you have ng-bind="title", you need to have a title variable on the scope, because ng-bind replaces the content of the HTML element it's on with what it's binded to:
<body>
<button class="btn btn-default" data-template="customer.tpl.html" bs-modal="modal">New Customer</button>
</body>
To see the text in the modal, either remove ng-bind="content" from the body, or assign content variable some value.
Working Plunker.
Source: http://mgcrea.github.io/angular-strap/##modals-examples

Bootstrap UI : Auto Tab Move with Time

I have a AnguleJS Bootstrp UI Horizontal Tab structure.
Once I click on Tab 2 the contents of Tab 2 displays and same for Tab 3.
My question is:
I want to implement in a way that after 3000 ms the Tab 2 auto display & after that Tab 3 without click on Tabs. and Once I click any particular Tab It Stops and display the content of that Tab.
Here is the Demo for Horizontal Tab view (Onclick): Plunker Demo
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="TabsDemoCtrl">
<tabset>
<tab ng-repeat="tab in tabs" heading="{{tab.title}}">
{{tab.content}}
</tab>
</tabset>
</div>
</body>
</html>
So there is a directive variable called active there you can pass a variable, that indicates if the tab should be active.
Put those variables into an array, set an interval and use an index to set the right tabs active.
My working plunker: PlunkerDemo
Maybe use angular's $interval.

Resources