How to reduce redundant code using angularjs? - javascript

dt.html and st.html are exactly same only difference in controller is scoket.on call dtconsumer vs stconsumer , How can i use one controller for both views or same view and controller for two different state. there is alot of redundant code in js and html. what is best approach to resolve this issue ?
Do i need to write directive ?
dt.html
<div class="panel-body display-logs" scroll-bottom="event" style="width:100%;">
<ul style="list-style: none;">
<li ng-repeat="message in event | limitTo:1000" ng-class="{lastItem: $last}"><span>{{message.value}}</span></li>
</ul>
</div>
Ctrl-1.js
var searchEnv = 'DT';
$scope.event = [];
socket.on('dtConsumer',function (data) {
var obj = {
file:$scope.filename,
data:data
}
var messageSize = getBytesForBuffer(data);
$scope.event.push(data);
});
Ctrl-2.js
var searchEnv = 'st';
$scope.event = [];
socket.on('StConsumer',function (data) {
var obj = {
file:$scope.filename,
data:data
}
$scope.event.push(data);
var messageSize = getBytesForBuffer(data);
});
app.js
.state('app.dt', {
url: '/dt',
templateUrl: 'view/partials/dt.html',
controller: 'DitCtrl'
})
.state('app.st',{
url:'/st',
templateUrl:'view/partials/st.html',
controller:'StCtrl'
})

You could pass dt/st via $stateParams, so you could keep 1 url with dt/st as a parameter. Something like this.
app.js
.state('app.dt', {
url: '/:type',
templateUrl: 'view/partials/dt.html',
controller: 'DitCtrl'
})
ctrl.js
var searchEnv = $stateParams.type;
$scope.event = [];
socket.on(searchEnv+'Consumer',function (data) {
var obj = {
file:$scope.filename,
data:data
}
var messageSize = getBytesForBuffer(data);
$scope.event.push(data);
});

Related

Why are the functions being called in my angular html bindings receiving null values?

I am creating a simple web app that represents something like a trip planner. Just offers some simple itinerary options from a list of locations in a DB I made. My feed page is supposed to display pictures of each attraction, and each attraction is a clickable card that will lead you to another page with some more info on that attraction.
//
// init app
var tripperApp = angular.module('tripperApp', ["ui.router", 'ionic', 'LocalStorageModule']);
//
// setup routing
tripperApp.config(function($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /state1
$urlRouterProvider.otherwise("/splash");
// Now set up the states
$stateProvider
.state('splash', {
url: "/splash",
templateUrl: "partials/splash.html",
controller: "splashCtrl"
})
.state("login", {
url: "/login",
templateUrl: "partials/login.html",
controller: "loginCtrl"
})
.state("signup", {
url: "/signup",
templateUrl: "partials/signup.html",
controller: "signupCtrl"
})
.state("reset-password", {
url: "/reset-password",
templateUrl: "partials/reset-password.html",
controller: "resetPasswordCtrl"
})
.state("set-password", {
url: "/set-password/:user_id/:password_reset_hash",
templateUrl: "partials/set-password.html",
controller: "resetPasswordCtrl"
})
.state("feed", {
url: "/feed",
templateUrl: "partials/feed.html",
controller: "feedCtrl"
})
.state("wishlist", {
url: "/wishlist",
templateUrl: "partials/feed.html",
controller: "wishlistCtrl"
})
.state("specificwishlist", {
url: "/wishlist/:user_id",
templateUrl: "partials/feed.html",
controller: "wishlistCtrl"
})
.state("share", {
url: "/share",
templateUrl: "partials/share.html",
controller: "shareCtrl"
})
.state("attraction", {
url: "/attraction/:attraction_id",
templateUrl: "partials/attraction.html",
controller: "attractionCtrl"
});
});
This is my app.js file where I initialize all my routings and controllers. I think I am literally having problems with everything (I have a backend and everything in Nodejs, but that isn't working right because all of the values it receives is null - more on that later...).
The main problem I am seeing is that nearly all the data I am receiving is null. Nothing is really loading right - but I know that I have a proper connection to my DB. Because there are some places where I can see the correct results. Let me explain:
This is my services/feed.js file (I don't think it's very important):
//
// feed service: used to get setup filters and then query for a feed using those filters
tripperApp.factory("feedService", ["$rootScope", "api", function($rootScope, api) {
var feedService = {};
api.get("filters").success(function(data, status, headers, config) {
$rootScope.filters = data;
})
.error(function(data, status, headers, config) {
// #TODO - gracefully handle error
});
feedService.runSearch = function($rootScope, session, callback) {
// add on more results
api.post("search", {
"start": $rootScope.currentSpot
})
.success(function(data, status, headers, config) {
// copy results into array
for (var i = 0; i < data.length; i++) {
$rootScope.results.push(data[i]);
}
$rootScope.currentSpot += data.length;
// call callback
callback(true); // success!
})
.error(function(data, status, headers, config) {
callback(false); // error!
});
};
feedService.getWishlist = function($rootScope, session, callback) {
// get all results
api.post("wishlist", {
"attraction_ids": session.picks
})
.success(function(data, status, headers, config) {
// copy results into array
$rootScope.results = data;
callback(true); // success!
})
.error(function(data, status, headers, config) {
callback(false); // error!
});
};
// column-related functions
$rootScope.columns = function() {
var columns = 1;
var windowWidth = window.innerWidth;
if (windowWidth > 1300) {
columns = 5;
} else if (windowWidth > 1100) {
columns = 4;
} else if (windowWidth > 640) {
columns = 3;
} else if (windowWidth > 300) {
columns = 2;
}
var rv = [];
for (var i = 0; i < columns; i++) {
rv.push(i);
}
return rv;
}
$rootScope.getColumn = function(data, columnNumber) {
var columns = $rootScope.columns().length;
var rv = [];
for (var i = columnNumber; i < data.length; i += columns) {
rv.push(data[i]);
}
return rv;
}
$rootScope.columnClasses = function() {
var columns = $rootScope.columns().length;
return {
"col-33": (columns == 3),
"col-25": (columns == 4),
"col-20": (columns == 5),
"col-50": (columns == 2)
};
}
// generate thumbnail of a url
$rootScope.thumb = function(filename) {
return filename + ".thumb.jpeg";
}
return feedService;
}]);
This is my controller (controller/feed.js) file:
//
// feed controller
tripperApp.controller("feedCtrl", function($scope, $rootScope, session, feedService, $ionicScrollDelegate) {
// setup feed page (only once)
if (typeof($rootScope.feed) == "undefined") {
// first time loading - setup scope
$rootScope.feed = {
results: [],
currentSpot: 0
}
}
// auto scroll down (if appropriate)
window.setTimeout(function() {
if (typeof($rootScope.feed.lastScrollPosition) != "undefined") {
$ionicScrollDelegate.$getByHandle('feedScroll').scrollTo(0, $rootScope.feed.lastScrollPosition, false);
}
}, 0);
// tell feed template that this is NOT for a wish
$scope.wishlist = false;
// don't display share button on feed
$scope.displayShare = function() {
return false;
}
// query and display results
$scope.loadResults = function() {
feedService.runSearch($rootScope.feed, session, function(success) {
if (!success) {
// #TODO - handle error
}
$scope.$broadcast('scroll.infiniteScrollComplete');
});
}
// whether an attraction is picked
$scope.attractionIsPicked = function(attraction_id) {
return session.picks.indexOf(attraction_id) != -1;
};
// when a result is picked/unpicked
$scope.resultPicked = function(result) {
var attraction_id = result.id;
console.log(result);
console.log(attraction_id);
if (session.picks.indexOf(attraction_id) == -1) {
// not yet picked, so lets pick it
session.pickPlace(attraction_id);
} else {
// its picked, so lets unpick it
session.unpickPlace(attraction_id);
}
}
$rootScope.clickedResult = undefined;
$scope.resultClicked = function(result) {
$rootScope.clickedResult = result;
console.log("result: \n");
console.log(result);
$rootScope.feed.lastScrollPosition =
$ionicScrollDelegate.$getByHandle('feedScroll').getScrollPosition().top;
}
});
There are a couple of functions I am specifically having problems with:
resultPicked() in controller/feed.js and thumb() in services/feed.js. I am getting null values for both of these.
My partial/feed.html file is as such:
<ion-view>
<ion-header-bar class="bar bar-positive" align-title="center">
<div class="buttons">
<button class="button ion-navicon-round button-light" ng-click="toggleLeftMenu(); " style="font-size: 22px"></button>
</div>
<h1 class="title" ng-show="wishlist==false">New York Attractions</h1>
<h1 class="title" ng-show="wishlist==true">
<span ng-show="feed.user.name == 'Your'">Your</span>
<span ng-show="feed.user.name != 'Your'">{{feed.user.name}}'s</span>
Wish List
</h1>
<div class="buttons" ng-show="displayShare()">
<button class="button ion-android-share button-light" style="font-size: 22px" ng-click="sharePage();"></button>
</div>
</ion-header-bar>
<ion-content class="padding feed-page" delegate-handle="feedScroll">
<ion-list>
<!-- display results in columns -->
<div class="row">
<div class="col" ng-class="columnClasses()" ng-repeat="column in columns()" >
<div class="card" ng-repeat="result in getColumn(feed.results, column)" ng-show="feed.results.length > 0">
<div class="item item-image">
<a>
<img ng-src="{{thumb(result.src)}}" ui-sref="attraction({attraction_id: result.id})" ng-click="resultClicked(result)">
</a>
</div>
<div class="item item-bottom-sect">
<div class="row">
<div class="col-75 col-wrap">
<a ui-sref="attraction({attraction_id: result.id})" ng-click="resultClicked(result)" class="item-title">{{result.title}}</a>
</div>
<div class="col-25 right col-wrap">
<span ng-click="resultPicked(result)">
<span class="ion-heart heart heart-selected" ng-show="attractionIsPicked(result.id)" class="heart-selected"></span>
<span class="ion-heart heart" ng-show="!attractionIsPicked(result.id)"></span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</ion-list>
<ion-infinite-scroll
ng-if="!resultsLoaded"
on-infinite="loadResults()"
distance="10%">
</ion-infinite-scroll>
</ion-content>
</ion-view>
Now, in my feed, there are two called to resultClicked() and one to resultPicked(). resultClicked(result) will return results just fine - but resultPicked(results) will always gets a null value! Also, thumb(result.src) always gets a null value. I have absolutely ZERO idea what - this is just things I'm confirming from console.logs. Is there anything glaringly wrong with the code?
Edit:
Here is a picture displaying what I am talking about. The cards are all "broken links" because the value im getting back is null (undefined) as shown in console. The "results" are also null, as shown in the console, when called from resultPicked(), but not from resultClicked().

Call a function to update some variables

I have a collection lines i get from ajax call and i use ng-repeat and for each item line the property line.date need some modification before to be displed
the problem is that I don't know how to call the function to make the modification ?
I try data-ng-init and ng-init the function is called but the variables are not updated !
Html code
<div ng-controller="lineController" data-ng-init="loadLines()">
<div ng-repeat="line in lines">
...
<div data-ng-init="loadDates(line.date)">
...
{{ leftDays}}
</div>
</div>
</div>
Js code :
var app = angular.module("searchModule", []);
app.controller("lineController", function ($scope, $http)
{
// LOAD LINES AJAX
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
angular.forEach(data.content, function(item, i) {
$scope.lines.push(item);
});
});
};
$scope.loadDates = function (date) {
// complex updating of date variable
....
$scope.leftDays = ...;
};
});
Why not manage each line in you angular.forEach?
Like this :
$http({method: 'GET', url: '..'}).success(function(data) {
angular.forEach(data.content, function(item, i) {
//Do stuff to item here before pushing to $scope.lines
//item.date = new Date(item.date) blah blah
$scope.lines.push(item);
});
});
If, you want line.date to be displayed in a different way in you html, and dont want to modify the actual data, why not use a $filter for that?
Like this :
<span ng-repeat="line in lines">{{line.date|yourCustomFilter}}</span>
I think you don't need to do this in this way. You can do this as follows;
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
angular.forEach(data.content, function(item, i) {
$scope.lines.push(item);
});
$scope.lines.map(function(line) {
// here is to modify your lines, with a custom
line.date = $scope.loadDates(line.date);
return line;
})
});
};
By the way, I think you can modify your ajax loading function with this;
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
$scope.lines = data.content.map(function(line) {
// here is to modify your lines, with a custom
line.date = $scope.loadDates(line.date);
return line;
})
});
};
And if you don't need to use loadDates function in view, you don't need to set this function to $scope. You can set this function with just var. Then you can use that function like; loadDates(...) instead of $scope.loadDates(...).
If you don't have to update that $scope.lines variable, you don't need to use .map for this. You can update that function as follows;
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
$scope.lines = data.content;
angular.forEach($scope.lines, function(line) {
// here is to modify your lines, with a custom
$scope.loadDates(line.date);
})
});
};

Not able to obtain value in view (directive)

I have an array in the profile-form.html directive's controller.
But I am neither able to obtain the value of that array (all_languages) nor iterate over it using ng-options in the directive. It's simply printing as string. I am new to Angular and maybe doing everything terribly wrong.
Directive
app.directive("profileForm", function() {
return {
restrict: "E",
templateUrl: "/static/translatorNgApp/profile-form.html",
controller: ['$scope','$http',function($scope, $http) {
this.getCookie = function(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
console.log(cookieValue);
return cookieValue;
};
$scope.csrftoken = this.getCookie('csrftoken');
$scope.myForm={};
$scope.all_languages = ['English', 'Hindi'];
$scope.language_pairs = [];
$scope.getAllLanguages = function () {
$http.get('/getAllLanguages'
).success(function(response) {
// success
$scope.all_languages.concat(response);
}).error(function(response) {
// failed
});
};
$scope.submitForm = function() {
var postData = {
method: 'POST',
url: '/accounts/tprofile/',
// headers : {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},
headers: {'X-CSRF-Token' : $scope.csrftoken },
data: $scope.myForm
};
$http(postData)
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
console.log("Form submitted");
// $scope.message = "Sent Successfully 2";
// console.log(postData);
console.log(postData);
console.log($scope.myForm);
};
$document.ready(function(){
console.log("document ready");
$scope.getAllLanguages(); //This can be commented out for the question's sake.
});
}],
controllerAs: "profileFormCtrl"
};
});
Directive Template (profile-form.html)
<div class="form-group" >
<label for="id_source_language">Source language: </label>
<ul>
<li>
<pre>all_languages = {{all_languages | json}}</pre>
<select data-ng-model="source" ng-options="language for language in all_languages" class="form-control" id="id_source_language" name="source_language" placeholder="Source Language" required>
</select>
<button ng-click="language_pairs.pop($index)" aria-label="Remove">Remove</button>
<button ng-click="language_pairs.push({})">Add more pair</button>
</li>
</ul>
</div>
Using document.ready event inside a angular directive doesn't make sense to call specific method of scope. Because document.ready event has already happened after that event only angular started process page.
Ideally to make your code working state you need to remove $document.ready(function(){ .... }); code which isn't required there. And as document.ready is already accomplished, so the one which you had registered from directive wouldn't get call.

Angularjs why this html page(view) does not integrate with Angular

I have an Angularjs site that works. However one html file(view) does not integrate with Angular. The flight fields are not show and the button is not active.
Can anybody help?
<nav class="top-bar" data-topbar="" role="navigation">
<ul class="title-area">
<li class="name"><h1><a ui-sref="client.payment">Pagamento</a></h1></li>
</ul>
</nav>
<div id="sidePanelContent">
<a ui-sref="^" ui-sref-opts="{reload: true}" class="closeSidePanel"><img src="images/admin/botao-fechar.png" alt="Fechar"></a>
<h1>Pagamento do Voo</h1>
<div>
<p ng-show="flight"><strong>Voo:</strong> {{flight.fromairport.name}} ➝ {{flight.toairport.name}}</p>
<p ng-show="flight"><strong>Horário:</strong> {{flight.departure | formatDateTime}}h</p>
<p ng-show="flight"><strong>Lugares disponíveis:</strong> {{flight.availableseats}}</p>
<p ng-show="flight"><strong>Aeronave:</strong> {{flight.airplane.name}}</p>
<p ng-show="flight"><strong>Preço atual:</strong> R$ {{flight.price | formatPrice}}</p>
</div>
<button class="button" ui-sref="client.payment({flight:flightid})" >Pagar com Paypal</button>
---------------- Java script -----------------
'use strict';
/**
* #ngdoc function
* #name flyvipApp.controller:AboutCtrl
* #description
* # AboutCtrl
* Controller of the flyvipApp
*/
angular.module('flyvipApp')
.controller('PaymentCtrl', function ($scope, SharedData, $rootScope, $state, $stateParams, Authorization, $http) {
var api = "http://flyvip.com.br/app/api/";
var userid = Authorization.currentUser().user.id;
$rootScope.sidePanel = false;
SharedData.selectedMenu.setItem('voos');
$scope.menu = SharedData.selectedMenu;
$rootScope.homeClient = false;
$scope.orderedFlights = {data: []};
$scope.flag = false;
var _flightid = _id;
var _airplaneid = $scope.flight.airplane.id;
var _dateofdeparture = $scope.flight.dateofdeparture;
var _dateofarrival = $scope.flight.dateofarrival;
var _airportdeparture = $scope.flight.fromairport.id;
var _airportarrival = $scope.flight.toairport.id;
var _price = $scope.flight.price;
var _seats = $scope.flight.availableseats;
var _status = $scope.flight.flightstatus;
var _reason = $scope.flight.reason;
var flight = {
flightid: _flightid,
airplaneid: _airplaneid,
dateofdeparture: _dateofdeparture,
dateofarrival: _dateofarrival,
airportofdeparture: _airportdeparture,
airportofarrival: _airportarrival,
price: _price,
seats: _seats,
flightstatus: _status,
reason: _reason,
invoicenum: "122344",
passengerid: $scope.passengerid
};
$http({method: "POST", url: api + "DoWriteLog.php",msg:'Entrei neste script!', headers: {'Content-Type': 'application/x-www-form-urlencoded'}}).success(function(response, status, headers, config) {
});
$http({method: "POST", url: api + "DoPayment.php", data: flight, headers: {'Content-Type': 'application/x-www-form-urlencoded'}}).success(function(response, status, headers, config) {
if (response.success) {
$scope.flag = true;
}
else
$scope.flag = false;
})});
You are not assigning flight object to scope try this:
$scope.flight = {
...
}
Also I can see that most of the variables are not declared in that object except flight.fromairport.
I'm not sure where are you getting the data from, but make sure it is assigned to $scope.flight at some point.

Angular Controller Loading Before Data Is Loaded

I am writing a simple app that loads movie info from an API. After this loading, I am attempting to use Angular to display the movies in a simple list view. I am correctly loading the movies, but it seems like the angular controller is created and sends the movie array to the view before the movie array is populated. I am unsure how to get around this.
var movieList = [];
var app = angular.module('top250', []);
// immediately make a call to the server to get data (array of movies from text file)
$.post('/', {}, function(data) {
init(data);
});
app.controller('MovieController', function() {
// should be setting this.movies to an array of 250 movies
this.movies = movieList;
});
function init(data) {
// cycle through array, use title to retrieve movie object, add to array to be sent to view
$.each(data, function(index, value) {
var title = value.split(' (')[0];
title = title.split(' ').join('+');
var url = 'http://www.omdbapi.com/?t=' + title + '&y=&plot=short&r=json';
$.getJSON(url, function(data) {
console.log('in get json', data);
var movieObj = data;
storeMovie(movieObj);
});
});
}
function storeMovie(movieObj) {
movieList.push(movieObj);
}
And my HTML (although I'm certain this isn't the problem:
<body ng-controller="MovieController as MovieDB">
<div class="row">
<div class="large-12 columns">
<h1>IMDB Top 250 List</h1>
</div>
</div>
<div class="row">
<div class="large-12 columns" id="movie-list">
<div class="list-group-item" ng-repeat="movie in MovieDB.movies">
<h3>{{movie.Title}} <em class="pull-right">{{movie.Plot}}</em></h3>
</div>
</div>
<script src="js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
</body>
First I transformed your ajax calls to an angular factory:
app.factory('MoviesService', function($http, $q) {
function getMovie(value) {
var title = value.split(' (')[0];
title = title.split(' ').join('+');
var url = 'http://www.omdbapi.com/?t=' + title + '&y=&plot=short&r=json';
return $http.get(url).then(function(res){ return res.data; });
}
return $http.post('/').then(function(res) {
return $q.all(res.data.map(getMovie));
});
});
Then I can consume it like so:
app.controller('MovieController', function(MoviesService) {
var self = this;
MoviesService.then(function(movies) {
self.movies = movies;
});
});
don't use jquery
use angular $http or $resource
using $http, you set scope var to the data inside promise, and life will be good
You need to wait for you init method to complete:
function init(data, complete) {
$.each(data, function(index, value) {
var title = value.split(' (')[0];
title = title.split(' ').join('+');
var url = 'http://www.omdbapi.com/?t=' + title + '&y=&plot=short&r=json';
$.getJSON(url, function(data) {
console.log('in get json', data);
var movieObj = data;
storeMovie(movieObj);
}).always(function(){ // count competed ajax calls,
// regardless if they succeed or fail
if(index === data.length -1)
complete(); // call callback when all calls are done
});
});
}
Now you can do this:
app.controller('MovieController', function() {
$.post('/', {}, function(data) {
init(data, function(){
this.movies = movieList;
});
});
});
Personally I would just keep the movieList inside of the init method and send it with the callback when you're done, but that's just a preference.

Categories

Resources