Currently, I can fetch the GET params via $location.$$search
.
However, I still have no idea how to do 2 way binding for the URL and FORM on the following case.
As the following demo picture, when user updates the FORM elements the corresponding URL should be: https://lazyair.co/en/user/quick_search/index#?from=TOKYO&to=TAIPEI&depart=2016/06/03~2016/06/06&return=2016/06/08~2016/06/11&chart_type=column&depart_slider=10:00~24:00
Demo page: https://lazyair.co/en/user/quick_search/index
'use strict';
quick_search_app.directive('ionslider',function($timeout){
var get_hour_minute, getHHMMformat, isDepartureAtInInterval;
get_hour_minute = function(value) {
var hours, minutes;
hours = Math.floor(value / 60);
minutes = value - (hours * 60);
if (hours.length === 1) {
hours = '0' + hours;
}
if (minutes.length === 1) {
minutes = '0' + minutes;
}
return [hours, minutes];
};
getHHMMformat = function(values) {
var hours, minutes;
hours = values[0].toString();
minutes = values[1].toString();
if (hours.length === 1) {
hours = '0' + hours;
}
if (minutes.length === 1) {
minutes = '0' + minutes;
}
return hours + ':' + minutes;
}
isDepartureAtInInterval = function(departure_at, slider){
var t = new Date(Date.parse(departure_at))
var HHMM_in_minutes = t.getUTCHours()*60 + t.getMinutes();
return slider.from <= HHMM_in_minutes && slider.to >= HHMM_in_minutes;
}
var updateFlighSeries = function(slider, flight_series) {
$.each(flight_series, function() {
var current_series = this;
angular.forEach(current_series.data, function(value, key) {
if(isDepartureAtInInterval(value.departure_at, slider)){
this.visible = true ;
}else{
this.visible = false ;
}
}, current_series);
});
}
return{
restrict:'AE',
scope: false,
controller: 'quick_search_ctrl',
link:function(scope, element, attr, ctrl){
$(element).ionRangeSlider({
hide_min_max: true,
keyboard: true,
min: 0,
max: 1440,
from: 0,
to: 1440,
type: 'double',
step: 30,
prefix: "",
chartConfig: element.attr("chart-config"),
grid: true,
prettify: function (value) {
return getHHMMformat(get_hour_minute(value));
},
onChange: function(slider) {
var _this = this;
updateFlighSeries(slider, scope[_this.chartConfig].series)
angular.forEach(scope.chart_names, function(chart_cfg_name){
scope.$apply(function () {
scope.lowestFlights[chart_cfg_name] = angular.copy(scope.filterLowestPrice(scope[chart_cfg_name]))
console.log(scope.lowestFlights[chart_cfg_name])
});
}, scope)
}
});
}
}
});
<ui-select.selectpicker{:theme => "select2", "ng-disabled" => "disabled", "ng-model" => "from", :name => "from", :theme => "select2", "ng-change"=>"updateDeparture(from)", :style => "width: 200px;", :required => "" }
<ui-select-match{ "ng-cloak"=>"", :placeholder => t("from") } {{$select.selected.t_name}} {{$select.selected.name}}</ui>
</ui>
<ui-select.selectpicker{"ng-disabled" => "disabled", "ng-model" => "to", :name => "to", :theme => "select2", "ng-change"=>"updateArrival(to)", :style => "width: 200px;", :required => ""}
<ui-select-match.selectpicker{"ng-cloak"=>"", :placeholder => t("to")} {{$select.selected.t_name}} {{$select.selected.name}}</ui>
<ui-select-choices{:repeat => "node in arrivals | filter: $select.search" }
<span ng-bind-html="node.t_name | highlight: $select.search"></span>
<span ng-bind-html="node.name | highlight: $select.search"></span>
</ui>
</ui>
$rootScope.Scope#$digest
cycleI put a breakpoint inside $locationChangeSuccess
and found the url params were cleared in $rootScope.Scope#$digest
cycle
app.run(function ($rootScope) {
$rootScope.$on('$locationChangeSuccess', function () {
debugger
console.log('$locationChangeSuccess changed!', new Date());
});
});
The 2-way binding not working on directive, Actually the 2-way binding works on View, but not working on URL params
DEMO page http://133.130.101.114:3000/en/user/quick_search/index
$scope.departChartName = "yoyoyo"
urlBinder.bind($scope, "departChartName", "DPNAME")
app.directive('ionslider',function($timeout){
return{
restrict:'AE',
scope: false,
link:function(scope, element, attr, ctrl){
$(element).ionRangeSlider({
chartName: element.attr("chart-name"),
onChange: function(slider) {
scope[this.chartName] = slider.from+"~"+slider.to
scope.$apply();
}
});
}
}
});
You can create a service to do a two way binding to a URL parameter:
angular.module('app').service('urlBinder', ['$location', function($location) {
this.bind = function(
scope, // angular scope
varName, // string : name of the variable on the scope to bind to
urlParamName // string : name of the url parameter to bind to
) {
// when scope variable changes, update the URL
var unhookUrlUpdater = scope.$watch(varName, function(newValue) {
$location.search(urlParamName, newValue);
});
// when the URL changes, update the scope variable
var unhookScopeUpdater = scope.$on('$locationChangeSuccess', function() {
var value = $location.search()[urlParamName];
if (!angular.equals(scope[varName], value)) {
scope[varName] = value;
}
});
// return a function that can be called to remove the bindings
return function() {
unhookUrlUpdater();
unhookScopeUpdater();
};
};
}]);
You can also do the same thing with getter/setter function instead of varName
if the things you are binding aren't on the scope:
angular.module('app').service('urlBinder', ['$location', function($location) {
this.bind = function(scope, getter, setter, urlParamName) {
var unhookUrlUpdater = scope.$watch(getter, function(newValue) {
$location.search(urlParamName, newValue);
});
var unhookScopeUpdater = scope.$on('$locationChangeSuccess', function() {
var value = $location.search()[urlParamName];
if (!angular.equals(getter(), value)) {
setter(value);
}
});
return function() {
unhookUrlUpdater();
unhookScopeUpdater();
};
};
}]);
In your controller:
var someVariable;
urlBinder.bind(
$scope,
function() { return someVariable; },
function(value) { someVariable = value; },
'url-name');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With