Navigation problems with pager.js - javascript

Im trying to implement pager.js in my knockout SPA.
It is working, sort of, however i am experiencing some strange behaviour, even though I have followed the official guide..
My page structure look like this.
<div data-bind="page: { id='start', title='index'}">
</div>
<div data-bind="page: { id='mainPage1', title='mainPage1'}">
</div>
//implement deep nav??
<div data-bind="page: { id='mainPage2', title='mainPage2'}">
//Grid page
<div data-bind="page: { id='start', title='grid'}">
//Error here - page dont exist? | URL output: mainPage2/detail
<a data-bind="page-href: '../detail' ">go to detail page.</a>
</div>
//Detail page
<div data-bind="page: { id='detail', title='detail'}">
</div>
</div>
Also when i type in the url I can navigate to mainPage2 by this url:
/mainPage1/dsjak/adsPae1/madaadsnPage1/mainPage2
Aslong as the last part of the url is valid it will navigate to that part of the page, is this intended?
Not sure if this can have anything to do with my Back end routing but it looks like this..
routes.MapRoute(
name: "Default",
url: "{*catchall}",
defaults: new { controller = "Home", action = "Index" }
);
I am also using require.js..

Your syntax is all wrong
e.g. id='start' change to id:'start'
it should be
<div data-bind="page: { id:'start', role: 'start', title:'index'}">start</div>
<div data-bind="page: { id:'mainPage1', title:'mainPage1'}">page 1</div>
<div data-bind="page: { id:'mainPage2', title:'mainPage2'}">
page2
<div data-bind="page: { id:'start', title:'grid'}">
//Error here - page dont exist? | URL output: mainPage2/detail
<a data-bind="page-href: '../detail' ">go to detail page.</a>
</div>
//Detail page
<div data-bind="page: { id:'detail', title='detail'}"></div>
</div>

Related

Passing Dynamic Data Between Two Controllers

I am looking to pass an item from a controller's $scope element (in this case the 'header' and 'content') to a page that is redirected-to upon a click.
The way it is currently set up is as follow:
- Page #1 loads the masterArray, displaying all elements
- User then clicks on a button which is linked with the 'href' attribute
- When user clicks an href button, the new page (Page #2) is displayed.
My Question: How can I pass the 'header' and 'content' onto Page #2 and ensure that only the associated header/content (based on the link that is clicked) are mapped and displayed?
The code below is for the main page with all the data dynamically being displayed
app.controller("SomeController", function ($scope, $window) {
$scope.masterArray = [{
title: "MainTitle",
segments: [{
title: "SubTitle",
articles: [{
header: "Article1Header",
content: "SomeContent",
href: "http://uniqueURL1.com"
}, {
header: "Article2Header",
content: "SomeContent",
href: "http://uniqueURL2.com"
}, {
header: "Article3Header",
content: "SomeContent",
href: "http://uniqueURL3.com"
}, {
header: "Article4Header",
content: "SomeContent",
href: "http://uniqueURL4.com"
}]
}
}]
}];
Page #1
<div ng-controller="SomeController">
<div class="section">
<div class="segment" ng-repeat="m in shownArray">
<div ng-repeat="s in m.segments" ng-if="m.segments">
<h4 ng-show="filtered.length">{{s.title}} ({{filtered.length}})</h4>
<div template="basic" ng-repeat="a in s.articles|articleFilter:query as filtered" is-open="a.isOpen">
<h2 ng-bind-html="a.header | highlight:query"></h2>
<div>
<p ng-bind-html="a.content | highlight:query"></p>
<a class="button button-primary" ng-href="{{a.href}}">View</a>
</div>
</div>
</div>
</div>
</div>
</div>
Page #2 (Desired Result)
<div>
<h2>//DISPLAYS ASSOCIATED 'header'</h2>
<h3>//DISPLAYS ASSOCIATED 'content'</h3>
</div>
If you want to use URL Params, use $location.search:
$rootScope.header = $location.search().header;
You can also use $routeParams if you prefer to build your URL differently.
Both would require you to properly build ng-href:
ng-href="{{a.href+'?header='+a.header+'&content='+a.content}}"
If your architecture allows it, consider a single page app, in which you'd configure states with $stateProvider in your config() then use ui-sref to access them in your HTML.

Tabbed navigation in Vue.Js

I'm trying to create a basic tabbed navigation system with Vue. I'm capturing user's navigation choice and calling a function which changes a certain data. That data is eventually going to determine which tab should be active. So far I have this:
HTML
<div id="app">
<div id="nav">
Home
Info
</div>
<div class="content">
<div class="boxes" id="home" v-bind:class="choice">
</div>
<div class="boxes" id="info" v-bind:class="choice">
</div>
</div>
</div>
Vue
new Vue({
el: '#app',
data: {
choice: 'homeActive' // Home is chosen by default
},
methods: {
makeActive: function(val) {
this.choice = val;
}
}
});
At the moment, if the user clicks on Home link, both home and info divs get homeActive class, this is because I couldn't manage to return two statements with my methods with this basic logic:
enable tab1 & disable tab2 || enable tab 2 & disable tab1
I'm trying different approaches but I can affect only a single state with called methods due to binding my content to a single class.
Any suggestions on how I can get this working with Vue?
The way I generally solve this is by adding another function isActiveTab like so...
new Vue({
el: '#app',
data: {
choice: 'homeActive' // Home is chosen by default
},
methods: {
makeActive: function(val) {
this.choice = val;
},
isActiveTab: function(val) {
return this.choice === val;
}
}
});
Then in your view...
<div id="app">
<div id="nav">
Home
Info
</div>
<div class="content">
<div class="boxes" id="home" v-show="isActiveTab('homeActive')">
</div>
<div class="boxes" id="info" v-show="isActiveTab('infoActive')">
</div>
</div>
</div>

Retain scroll position when a button is toggled

I am working on an angularJS application which has a page where I display around 30 items using ng-repeat. In front of each item, there is a toggle button (enabled/disabled). With the current code that I have, I can toggle these items. But the problem is if I scroll down and toggle lets say item 25, then automatically it scrolls to the top of the page. If I now scroll down, I can see that the toggle actually took place.
So the requirement now is to make sure that the scroll position is retained after the toggle button is clicked.
Please see below the code that I have.
HTML
<div id="eventTypes" class="panel-body">
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
<div ng-if="spinner" class="spinner">
<div class="spinner-container container1">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container2">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container3">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
</div>
</div>
JS
(function () {
'use strict';
angular.module('myApp').controller('itemsController', function ($scope, itemsService) {
var serviceError = function (errorMsg) {
console.log(errorMsg);
$scope.turnOffSpinner();
};
$scope.items = [];
$scope.item = {};
$scope.spinner = true;
$scope.toggleEnabled = function (item) {
$scope.turnOnSpinner();
itemsService.toggleEnabled(item)
.then(function () {
$scope.loaditems();
});
};
$scope.loaditems = function () {
itemsService.getitems().then(function (response) {
$scope.items = response.data;
}, serviceError);
$scope.turnOffSpinner();
};
$scope.turnOnSpinner = function () {
$scope.spinner = true;
};
$scope.turnOffSpinner = function () {
$scope.spinner = false;
};
$scope.loaditems();
});
}());
How this works right now is, once I click the toggle button, a spinner is enabled. Meanwhile the controller will call the itemService.toggleEnabled() method which does an ajax call to the server to just change the status of the item(enabled to disabled or vice-versa) in the backend. On successful change of the status and when the ajax call returns, the $scope.loadItems() method is called in the controller. This method will then do another ajax call to fetch the items (now with the updated status of the item that was toggled). The spinner is disabled and the data is then displayed on the UI.
When all of this is done, the page is scrolled to the top. This is annoying when I want to toggle an item which is way down in the list.
I want the page to be present at the same position when I clicked the toggle button of the corresponding item and not scrolling up to the top.
I am new to AngularJS and any help in this regard would be really helpful.
It looks like your spinner scheme is what's causing you problems:
...
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
...
<div ng-if="spinner" class="spinner">
...
Whenever you click your button, you are removing every single element in your ng-repeat from the DOM when you $scope.turnOnSpinner(). That's why it appears to jump to the top. It's not really jumping, there just aren't enough DOM elements to fill up the page, making the page so short that the scrollbar disappears (even if it's only for a second). Then when the spinner is done, your ng-repeat fills up the page with DOM elements again, resulting in your scroll position being lost.
So basically what you are trying to fix is a symptom of a less than ideal loading spinner implementation.
ng-if is a "brutal" way of hiding things in Angular. It's mostly meant to hide things for a longer period of time than "softer" directives like ng-show/ng-hide. One solution to your problem is to use ng-disabled on each one of your buttons to prevent the user from interacting with it while the spinner is active, rather than doing a hard removal of each element:
Before:
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
After:
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
ng-disabled="spinner"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
Another solution, which I really like and use myself is this Angular module: https://github.com/darthwade/angular-loading
You can attach it to any element in the page and it will put a loading spinner over it and prevent you from interacting with it until your ajax or whatever is done.
If you don't like either of those, try putting your ng-repeat into a container that you can use to prevent interaction with your elements when the spinner is up:
<div class="container" ng-class="{'you-cant-touch-this': spinner}">
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
</div>
Now you can style it in some way to prevent interaction without having to remove all those items from the DOM:
.you-cant-touch-this {
pointer-events: none;
}

Create custom follow button for my application

I would like a directive that dynamically knows if I'm following the user in my App.
I have a resource to get the currentUser
this.following = function () {
var defer = $q.defer();
var user = $cookies.getObject('currentUser');
UserResource.get({id: user.id}).$promise.then(
function (data) {
defer.resolve(data.following);
});
return defer.promise;
};
This is in one of my services. It returns all users that I'm following.
When instantiating my controller I fetch the users I follow within my app:
UserService.following().then(
function (data) {
$scope.following = data;
});
I would like to move that into a directive so that I can easily reuse it somewhere else in my app.
This is the HTML I am using right now (and it's not really beautiful) :
<div class="item" ng-repeat="user in users">
<div class="right floated content">
<div ng-show="isFollowing(user)" class="ui animated flip button" tabindex="0"
ng-click='unFollow(user)'>
<div class='visible content'>
Following
</div>
<div class="hidden content">
Unfollow
</div>
</div>
<div ng-hide="isFollowing(user)" ng-click="follow(user)" class="ui button">Follow</div>
</div>
</div>
But instead something like :
<div class="item" ng-repeat="user in users">
<um-follow-button um-user="user"></um-follow-button>
</div>
then depending if I'm following the user or not then render one of the two options.
I don't know if I will have to use a controller in my directive.
I have looked at : https://gist.github.com/jhdavids8/6265398
But it looks like a mess.

Angular Image Conditions

Bascially what i am doing at the moment is calling a jsonp array which contains an image url for an icon which works fine and displays fine except the icons suck. What i want to do is replace the icons with my own but the problem is that they are dynamic as its a weather api so the icon link will change to a different icon when the weather changes. What i can get from the json is the status of the weather eg partially cloudy and use that to somehow call a specific img. How would i go about this is in angular js?
var app=angular.module('app');
app.controller('MainCtrl', function($scope, $http) {
$http.jsonp('http://api.wunderground.com/api/5ad0204df4bdbeff/conditions/q/Australia/Melbourne.json?callback=JSON_CALLBACK').success(function(data){
$scope.currentMelbourne=data;
});
$http.jsonp('http://api.wunderground.com/api/5ad0204df4bdbeff/conditions/q/Australia/Sydney.json?callback=JSON_CALLBACK').success(function(data){
$scope.currentSydney=data;
});
$http.jsonp('http://api.wunderground.com/api/5ad0204df4bdbeff/conditions/q/Australia/Adelaide.json?callback=JSON_CALLBACK').success(function(data){
$scope.currentAdelaide=data;
});
$http.jsonp('http://api.wunderground.com/api/5ad0204df4bdbeff/conditions/q/Australia/Darwin.json?callback=JSON_CALLBACK').success(function(data){
$scope.currentDarwin=data;
});
$http.jsonp('http://api.wunderground.com/api/5ad0204df4bdbeff/conditions/q/Australia/Perth.json?callback=JSON_CALLBACK').success(function(data){
$scope.currentPerth=data;
});
$http.jsonp('http://api.wunderground.com/api/5ad0204df4bdbeff/conditions/q/Australia/Cairns.json?callback=JSON_CALLBACK').success(function(data){
$scope.currentCairns=data;
});
$http.jsonp('http://api.wunderground.com/api/5ad0204df4bdbeff/conditions/q/Australia/Brisbane.json?callback=JSON_CALLBACK').success(function(data){
$scope.currentBrisbane=data;
$scope.cityData=[
{ name:'Brisbane',
temp:$scope.currentBrisbane.current_observation.temp_c,
image:$scope.currentBrisbane.current_observation.icon
},
{ name:'Melbourne',
temp:$scope.currentMelbourne.current_observation.temp_c,
image:$scope.currentMelbourne.current_observation.icon
},
{
name:'Adelaide',
temp:$scope.currentAdelaide.current_observation.temp_c ,
image:$scope.currentAdelaide.current_observation.icon
},
{ name:'Darwin',
temp:$scope.currentDarwin.current_observation.temp_c ,
image:$scope.currentDarwin.current_observation.icon
},
{ name:'Perth',
temp:$scope.currentPerth.current_observation.temp_c ,
image:$scope.currentPerth.current_observation.icon
},
{ name:'Cairns',
temp:$scope.currentCairns.current_observation.temp_c,
image:$scope.currentCairns.current_observation.icon
},
]
});
});
Here is the html
<div id="weather-container">
<div id="current-weather">
<!--Angular JSON pull -->
<div id="title"><span id="current-title">Current Weather</span></div>
<div id="current-condition">{{currentSydney.current_observation.weather}}</div>
<!--Image thingo here-->
<img ng-src="{{currentSydney.current_observation.icon_url}}"></img>
<div id="current-temp"><span id="current-temp"> {{currentSydney.current_observation.temp_c}} </span></div>
<span id="current-city">{{currentSydney.current_observation.display_location.city}} </span>
</div>
<!--Angular JSON pull and iteration-->
<div id="other-city-container">
<div class="other-city-weather" ng-repeat="city in cityData" >
<!--Image thingo here-->
<img ng-src="{{city.image}}"></img>
<div class="current-city-temp">
<span>{{city.temp}}</span>
</div>
<div class="current-city-lower">
<span>{{city.name}}</span>
</div>
</div>
</div>
</div>
You can write an helper function which will be rewrite the url property in your json after each succeeded ajax request. Please provide more informations, so we can help you.

Categories