I am building an app for a scheduler using Appgyver Steroids, and on the navbar, I have a button to switch days, but I can't figure out how to switch de label:
index.html
<script src="/scripts/application.js"></script>
<super-navbar-button ng-bind="dayTitle" side="right" onclick="supersonic.ui.drawers.open('right')">Day</super-navbar-button>
drawerMenu.html
<script src="/scripts/application.js"></script>
<li class="item" onclick="supersonic.ui.drawers.close('right')" ng-model="day" ng-click="newDay()">Monday</li>
<div style="clear: both;"></div>
<li class="item" onclick="supersonic.ui.drawers.close('right')" ng-model="day" ng-click="newDay()">Tuesday</li>
<div style="clear: both;"></div>
application.js
angular.module('SteroidsApplication', [
'supersonic'
])
.controller('IndexController', function($scope, supersonic) {
$scope.newDay= function(){
supersonic.logger.log("Got here");
$scope.dayTitle= $scope.day;
}
});
Right now I'm not even logging the "Got here" text, probably I have a minor error or something I'm missing. This is my first steroids/supersonic/angular/hybrid application. Thanks in advance.
two things dont do onclick with angular, instead do ng-click
did you tried doing
{{ day }}
instead of writing the day?
Related
A few months ago I've be created the topic: Try to render two templates in same View (Ui-Router), where I asked about how to render multiple views in the same page. My objective with this was created a web app as an desktop one, with views to minimize, maximize, close and stuff like that.
Well, my app is ready but I'm getting a problem, when I up my app to the production some computers are taking a long time to render all the Views. In the image bellow we can se a lot of requisitions that server take to return my templatesURL's.
There is a way to avoid this ? I was looking for an lazy load to templateURL but I Didn't find any. :(
This plunkr was the approach what I used. I have only one state for all my Views (My current app.config has 103 Views):
routerApp.config(function($stateProvider) {
$stateProvider.state('mainState', {
views: {
'CompanyView': {
templateUrl: 'Company.html'
},
'PeopleView': {
templateUrl: 'People.html'
},
.....
....
}
})
});
Introduction
The way you approached the solution is the cause of the problem you're facing, because you have too many views for a single state, it'll end up having to load all of them in order to set that state, so every time you access your state, ui-router has to load every template in order to set the views. It might not cause problem for a few number of templates, but, for larger numbers like yours it is definitely an issue.
Ng-Templates
You can try to cache your templates in your page using <script type="text/ng-template"... in order to prevent the loading time, it's a good practice by the way. Usually it's part of the production build optimization, load all templates in the template cache, so that the application load time decreases significantly provided that you don't have to wait for an http call to load a page. It will indeed increase the performance in your case, but I don't have a benchmark that ensure if it'd be enough for your scenario.
Component Based Solution
Anyhow, you can always implement interface components to behave the way you want, optimized in such a way that it doesn't have to load one hundred templates to show a single panel for the user.
My suggestion is, instead of using ui-router, use a component based solution, create a directive component to hold the panel content of each window and its behavior; and use a controller to manage the state of opened and closed panels, holding and managing each opened panel in a list and so on. For example:
<nav>
<button ng-click="openPanel({title: 'My Panel Title', templateUrl: 'myPanel.html'>">
Open myPanel
</button>
<nav>
<main>
<panel ng-repeat="panel in openedPanels"></panel>
</main>
The following snippet implements this approach using bootstrap 4 css, each panel is a bootstrap card, and it has a list of panels it can open and on click of a nav list it adds the respective panel to the opened panels list where angularjs can render it on the html using ng-repeat. This way, only the opened window will be rendered, therefore, only the opened window template will be loaded.
Disclaimer: This is a very simple example implemented not using the best practices available out there. If you intend to use this approach you should implement it based on your application to fit better the needs of your architecture, this one is not a complete functional component, it's just an example for the sake of the demonstration.
angular.module('app', [])
.controller('PanelsCtrl', function($scope) {
// available windows to be opened
$scope.panels = [
{ title: 'Window 1', templateUrl: 'window1.html' },
{ title: 'Window 2', templateUrl: 'window2.html' }];
// all currently opened panels
$scope.openedPanels = [];
// opens a panel (a.k.a, adds a panel
// to the opened panels list)
$scope.openPanel = function(panel) {
if ($scope.openedPanels.indexOf(panel) === -1)
$scope.openedPanels.push(panel);
};
// close a panel (a.k.a, removes a panel
// from the opened panels list)
$scope.onClosePanel = function(panel) {
$scope.openedPanels.splice($scope.openedPanels.indexOf(panel), 1);
};
})
.directive('window', function($templateRequest, $templateCache, $compile) {
return {
restrict: 'E',
scope: {
panel: '=',
onClosePanel: '&'
},
template: `
<div class="card">
<h4 class="card-header">
<span>{{ panel.title }}</span>
<button
ng-click="onClosePanel(panel)"
type="button"
class="close"
data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</h4>
<div class="card-body">
<ng-include src="panel.templateUrl"></ng-include>
</div>
</div>
`
}
})
// example controlelr to be used with ng-controller
.controller('Window1Ctrl', function($scope) {
$scope.window1Prop = 'This is a property from Window1Ctrl'
})
#import 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css'
<div ng-app="app">
<div class="container" ng-controller="PanelsCtrl">
<div class="row">
<div class="col-sm-3">
<ul class="nav flex-column">
<li class="nav-item" ng-repeat="panel in panels">
<a class="nav-link active" href="#" ng-click="openPanel(panel)">
{{ panel.title }}
</a>
</li>
</ul>
</div>
<div class="col-sm-9">
<window ng-repeat="panel in openedPanels" panel="panel" on-close-panel="onClosePanel(panel)">
</window>
</div>
</div>
</div>
<!-- NG-TEMPLATES -->
<script type="text/ng-template" id="window1.html">
<div ng-controller="Window1Ctrl">
<b>{{panel.title}}</b>
<h5>window1Prop: {{ window1Prop }}</p>
</div>
</script>
<script type="text/ng-template" id="window2.html">
<em>{{panel.title}}</em>
</script>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
I want a live search: the results are queried from web api and updated as the user types.
The problem is that the list flickers and the "No results" text appears for a fraction of second, even if the list of results stays the same. I guess I need to remove and add items with special code to avoid this, calculating differences between arrays, etc.
Is there a simpler way to avoid this flicker at least, and probably to have possibility to animate the changes?
It looks like this now:
The html part is:
<div class="list-group">
<a ng-repeat="test in tests track by test.id | orderBy: '-id'" ng-href="#/test/{{test.id}}" class="list-group-item">
<h4 class="list-group-item-heading">{{test.name}}</h4>
{{test.description}}
</a>
</div>
<div ng-show="!tests.length" class="panel panel-danger">
<div class="panel-body">
No tests found.
</div>
<div class="panel-footer">Try a different search or clear the text to view new tests.</div>
</div>
And the controller:
testerControllers.controller('TestSearchListCtrl', ['$scope', 'TestSearch',
function($scope, TestSearch) {
$scope.tests = TestSearch.query();
$scope.$watch('search', function() {
$scope.tests = TestSearch.query({'q':$scope.search});
});
}]);
You should use ng-animate module to get the classes you need for smooth animation. For each ng-repeat item that's moved, added, or removed - angular will add specific classes. Then you can style those classes via CSS or JS so they don’t flicker.
An alternative way of doing what you require is to use the angular-ui bootstrap Typeahead component (check at the bottom of the post). It has a type-ahead-wait property in milliseconds and also a template url for customising it.
<div ng-app>
<div ng-controller="MyController">
<input type="search" ng-model="search" placeholder="Search...">
<button ng-click="fun()">search</button>
<ul>
<li ng-repeat="name in names">{{ name }}</li>
</ul>
<p>Tips: Try searching for <code>ann</code> or <code>lol</code>
</p>
</div>
</div>
function MyController($scope, $filter) {
$scope.names = [
'Lolita Dipietro',
'Annice Guernsey',
'Gerri Rall',
'Ginette Pinales',
'Lon Rondon',
'Jennine Marcos',
'Roxann Hooser',
'Brendon Loth',
'Ilda Bogdan',
'Jani Fan',
'Grace Soller',
'Everette Costantino',
'Andy Hume',
'Omar Davie',
'Jerrica Hillery',
'Charline Cogar',
'Melda Diorio',
'Rita Abbott',
'Setsuko Minger',
'Aretha Paige'];
$scope.fun = function () {
console.log($scope.search);
$scope.names = $filter('filter')($scope.names, $scope.search);
};
}
How can I open a page, which contains an ons-tabbar inside, and tell it to show a specific tab, using ons-navigator? I have a menu with some buttons, and depending which one is pushed, it has to be displayed the tabbar page, with a specific tab active.
This is what I have tried so far:
index.html (Main page)
<body>
<ons-navigator animation="slide" var="app.navi">
<ons-page>
<ons-toolbar>
<div class="center">Inicio</div>
</ons-toolbar>
<div>
<p style="text-align: center">
<ons-button modifier="large" ng-click="app.navi.pushPage('tabs.html', {params: { tab: 0 }});">OPEN TAB 0</ons-button>
</p>
<p style="text-align: center">
<ons-button modifier="large" ng-click="app.navi.pushPage('tabs.html', {params: {tab: 1}});">OPEN TAB 1</ons-button>
</p>
</div>
</ons-page>
</ons-navigator>
</body>
tabs.html
<div ng-controller="TabsCtrl">
<ons-tabbar var="tabbar" position="top">
<ons-tabbar-item
icon="home"
label="Home"
page="page0.html"></ons-tabbar-item>
<ons-tabbar-item
icon="comment"
label="Comments"
page="page1.html"></ons-tabbar-item>
</ons-tabbar>
</div>
AngularJS controller:
angular.module('myControllers', [])
.controller('TabsCtrl', ['$scope', function ($scope) {
// Trying to set active tab on the controller
$scope.tabbar.setActiveTab($scope.ons.navigator.getCurrentPage().options.params.tab);
}]);
However, when I push a buton in the main page, the debugger says that cannot call method setActiveTab on undefined. I know that this may be because the tabbar hasn't been created when the controller is executed, but I can't figure out how to show a specific tab when the page is displayed, based on some navigator parameter.
Yeah it's true that when the controller is executed there won't be any tabbar object, but it will be created immediately after.
So you could use setImmediate(fn) in the controller to call setActiveIndex(idx).
Example:
angular.module('app', ['onsen'])
.controller('TabsController', function() {
setImmediate(function() {
var tabIndex = app.navi.getCurrentPage().options.params.tab;
app.tabbar.setActiveTab(tabIndex);
});
});
Pen:
http://codepen.io/argelius/pen/XJryPM
Actually, in 1.2.0 there is an 'ons-tabbar:init' DOM event that you could listen to which is probably better to use. The event object will attach the tabbar object so you could do something like:
someElement.addEventListener('ons-tabbar:init', function(event) {
var tabBar = event.component;
tabBar.setActiveTab(someIndex);
});
So I followed this guide so I could have a nav bar on every page: http://tomaszdziurko.pl/2013/02/twitter-bootstrap-navbar-angularjs-component/
And it was working, until I created a separate controller to populate my bootstrap carousel. The thing is, my ng-repeat works fine, but when it does I can't see my navbar on that page. I can see it just fine on other pages. I believe this is a scoping issue, but I am not sure where.
This is what I have in the main body of this page:
<body>
<reusable-navbar></reusable-navbar>
<!-- Carousel Start -->
<div id="main-carousel" class="carousel slide container" data-ride="carousel">
<!-- Wrapper for slides -->
<div class="carousel-inner">
<!--Must set this by hand-->
<div class="item active">
<img alt="" src="../Revamp/Images/carousel/1.jpg">
</div>
<!--Repeat through the rest-->
<div ng-controller="carouselPhotoController">
<div class="item" ng-repeat="source in source">
<img alt="" ng-src="{{source.source}}">
</div>
</div>
</div>
</div>
And my controller looks like this:
var carouselPhotoController=angular.module("revampApp", []);
carouselPhotoController.controller("carouselPhotoController", function($scope, $http){
$http.get('../Revamp/Images/carousel/photos.json').success(function(photos){
//Carousel photos
$scope.source = photos;
})
});
And the directive is identical to the one in that walk through, just with a different template. So how to I get it so my nav bar will show up AND I can use ng-repeat?
Make sure you are not recreating the app.
This creates a new app:
var carouselPhotoController=angular.module("revampApp", []);
But this only accesses an app already created (note the absence of the second parameter):
var carouselPhotoController=angular.module("revampApp");
Change the above line and it should work.
I have a page where I have included the (Twitter) bootstrap.
On this page I have a prefectly working accordion and within that accordion I have a collapsable div. See the code below:
<div class="accordion" id="checkListAccordion">
<div ng-repeat="item in items" class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="#checkListAccordion" href="#collapse{{item.$$hashKey}}">{{item.name}}</a>
</div>
<div id="collapse{{item.$$hashKey}}" class="accordion-body collapse">
<div class="accordion-inner">
<div class="container-fluid">
<div class="row-fluid">
<div class="badges span12">
<span class="badge badge-info" data-toggle="collapse" data-target=".info{{item.$$hashKey}}"><i class="icon-info-sign icon-white"></i></span>
<div class="info{{item.$$hashKey}} collapse in">
{{item.info}}
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
some text
</div>
</div>
</div>
</div>
</div>
</div>
Now, when I click the info badge, the div with the corresponding class is folding open. But it never folds back when I click it again. Only when I wrap in in a navbar and navbar-inner, it folds back....but of course, I don't want that.
Any help on this?
When i add a controler to your code all seems to work as expected:
angular.module('plunker',[]);
function AccordionDemoCtrl($scope) {
$scope.oneAtATime = true;
$scope.items = [
{
name: "Dynamic Group Header - 1",
info: "Dynamic Group Body - 1"
},
{
name: "Dynamic Group Header - 2",
info: "Dynamic Group Body - 2"
}
];
}
See also: http://plnkr.co/nX4kvMThA0bYwcbXZS7t May be there will be a problem with the versions you use? I used jQuery 1.9.1, Twitter Bootstrap 2.3.1 and angularJS 1.0.7 (see: Angular JS Bootstrap Accordian Example).
btw have you consider to use UI Bootstrap (http://angular-ui.github.io/bootstrap/) see: http://plnkr.co/u7l6nrkPZM8ZJtA08RNP (thanks to winkerVSbecks who answered Howto set template variables in Angular UI Bootstrap? (accordion))