Select2 with ajax remote data options component in Vuejs - arrays

I wanna to use select2 with ajax remote data options in Vuejs 2.x. In vuejs.org website located a sample for select2 component that work as static, but I need to select2 with this specific for my project. How to convert JSFIDDLE Example to select2 that call an API with keyboard type.
In jQuery Select2 use this code for ajax call:
$('.js-data-example-ajax').select2({
ajax: {
url: 'https://api.github.com/search/repositories',
dataType: 'json'
// Additional AJAX parameters go here; see the end of this chapter for the full code of this example
}
});

Here is component that is working for me. Reference to their select2
https://v2.vuejs.org/v2/examples/select2.html
The gotcha for me was using change.select2 instead of triggering change event in the watch. change event causes infinite loop.
Your callback/ajax URL will need to return data with at least .id and .text properties. See this URL for proper format https://select2.org/data-sources/formats
<select2 v-model="member" name="member" callback="/res/member/select2.php" placeholder="Type a name"></select2>
Vue.component('select2', {
props: ['name', 'value', 'required', 'callback', 'placeholder'],
template: '<select :name="name" v-bind:class="{required: required}" class="vue-select2"></select>',
watch : {
value : function(value) {
$(this.$el).empty().append('<option value="' + value.id + '">' + value.text +'</option>').trigger('change.select2');
}
},
mounted: function() {
var that = this;
var options = {
width: '100%',
placeholder: this.placeholder,
allowClear: true,
ajax: {
url: this.callback,
dataType: 'json'
}
};
$(this.$el).select2(options);
$(this.$el).on('change', function() {
var item = $(this).select2('data')[0];
that.$emit('input', item);
});
}
});

Related

ui-angular fullcalendar refresh issue

I'm using ui-calendar to display events. To fill out the calendar model, the controller fetches the events from a Factory. The wierd part (which I can't figure out), is that when the Factory fetches the data from the API, the calendar shows the events just fine. However, in order to "speed things up" a little, the Factory saves the api fetched data in a local variable. If the Factory returns the data from the local variable, the calendar does not display the events. However if the Factory returns data from the API, the events are displayed just fine (so there must be something wrong with the way I am returning the local variable data from the Factory).
The Factory method is as follows:
function getAll() {
if (!_allEventsRequiresUpdate && _allEvents) {
var deferred = $q.defer();
deferred.resolve(_allEvents);
return deferred.promise;
}
else {
var request = $http({
method: "Get",
url: baseUrl
});
return request.then(function (response) {
_allEvents = response.data;
_allEventsRequiresUpdate = false;
return response.data;
}, handleError);
}
}
The _allEvents variable get filled when the data is fetched from the API. The data in both cases (returned from the API or the local variable), is exactly the same (at least to my knowledge), however, as stated previously, only the data fetched from the API gets rendered in ui-calendar/fullcalendar.
Any ideas? Is there something wrong as to how I am returning the local variable from the Factory?
BTW, in both cases, the controller resolves the promise.
UPDATE
The following is the method in the Angular controller that fetches the data from the Factory:
function getAllEvents() {
serviceAppointmentsServices.getAll()
.then(function (data) {
vm.events = angular.copy(data);
vm.fullCalendarEvents = [];
for (var i = 0; i < vm.events.length; i++) {
var event = {
id: vm.events[i].xrmId,
title: vm.events[i].xrmName,
start: moment(vm.events[i].startDate).tz('America/Santiago'),
end: moment(vm.events[i].endDate).tz('America/Santiago'),
stick: true
}
if (vm.events[i].xrmStatus.value == 1)
event.color = '#D2A15D';
vm.fullCalendarEvents.push(event);
}
uiCalendarConfig.calendars["calendar"].fullCalendar('removeEventSources');
uiCalendarConfig.calendars["calendar"].fullCalendar('addEventSource', vm.fullCalendarEvents);
}, function (mesage) {
toastr.error(mesage, "error!");
});
}
Here is the calendar config:
vm.uiConfig = {
calendar: {
height: 450,
editable: true,
eventClick: editEvent,
dayClick: addEvent,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize,
eventAfterAllRender: documentReady,
locale: 'es',
timezone: 'America/Santiago',
customButtons: {
addEvents: {
text: 'nuevo',
click: function () {
vm.fx.addEvent();
$scope.$apply()
}
}
},
header: {
left: 'month basicWeek basicDay agendaWeek agendaDay',
center: 'title',
right: 'addEvents today prev,next'
},
eventRender: eventRender
}
};
I'm posting the answer in case anyone else out there gets into the same issue.
Thanks to #Javarome (https://stackoverflow.com/users/650104/javarome) in the post: Directive is being rendered before promise is resolved. I followed his suggestion and everything worked like a charm.
Summary: the issue was that the directive was getting fired before the promise resolved in the controller. So I followed his suggestion to wrap the directive in an ng-if (with the variable needed to be resolved as the trigger, and voila!!! Something like this:
<div class="container" ng-if="vm.fullCalendarEvents">
<div class="calendar" ng-model="eventSources" calendar="calendar" config="uiConfig.calendar" ng-disabled="waitingForHttp" ui-calendar="vm.uiConfig.calendar" ></div>
</div>

AngularJS Include Refresh

I have a html page which I am including as follows.
<ng-include src="lowerTabURL"></ng-include>
This page contains a devextreme control which loads a datasource via ajax.
html:
<div class="tab-container" style="height:100%; width:100%">
<div dx-tabs="lowerTabOptions" dx-item-alias="lowerTab">
</div>
</div>
controller:
DemoApp.controller('NavigationController', function DemoController($scope, $templateCache) {
$scope.lowerTabURL = "LowerPanelTest";
$scope.currentSidebarId = 10100;
$scope.lowerTabOptions = {
dataSource: new DevExpress.data.CustomStore({
load: function (loadTabOptions) {
console.log('get tabs');
var d = $.Deferred();
$.ajax({
url: 'GetLowerTabs',
data: { currentSidebarId: $scope.currentSidebarId },
type: 'GET',
success: function (result) { console.log(result); d.resolve(result); }
});
return d.promise();
}
}),
animationEnabled: true,
swipeEnabled: true,
itemTitleTemplate: 'title',
height: '100%'
};
$scope.navBarClicked = function (sidebarId) {
console.log(sidebarId);
$scope.currentSidebarId = sidebarId;
}
});
This works correctly however I have a navbar which when clicked, should change the tab control.
Currently I am changing the sidebarId which gets passed to the ajax call but I need a way to reload the include page so that this is called again. I have tried changing the lowerTabUrl and then changing it back again but this doesnt refresh the page. What is the best way to do this?
It depends on your angular version, you will need to watch after changes of value for param sidebarId, # angular 1 this is achieved by scope.watch
scope.$watch('sidebarId', function(newValue, oldValue) {
// ..call refresh here
});
at angular 1.5 and later you can override ngOnChages
this.$onChanges = function (changesObj) {
if (changesObj.sidebarId) {
// changesObj.sidebarId.currentValue
}
};

Angular JS - Update Scope value on click

Right now I am passing my parameter through the state like:
.state('app.listing', {
url: '/ad/listing/:adId/{type}',
params: {
adId: {
value: "adId",
squash: false
}, type: {
value: null,
squash: true
}
},
This works as I can get "type" from $stateParams and update my get request.
Is there not a way to do this from a click event and not use $stateParams for passing the "type" param?
I basically have a button that filters results and passes the type param from the button. It would be a lot easier if I can just attach a click event to it which then updates my get request.
Just messing around I tried doing something like
$scope.filter = function(type) {
if(type) {
return type;
}
return '' ;
}
$scope.type = $scope.filter();
Service is like
$http.get(API_ENDPOINT.url + '/listing/' + adId, {
params: {
page: page,
type: type // essentially $scope.type
},
}).
and then on my button I have
<button ng-click="filter('2')"></button>
^ This will pass 2 for type, but won't reinit the http get call on click. Do I need to broadcast the change is there a simple way to do this?
Does this even make sense? The code above is just mock to give an idea, but open to suggestions if any.
Angular never requires you to make broadcasts to reflect changes made to scopevariables via the controller
var typeWatcher = '1';
$scope.filter = function(type){
if (type !== typeWatch)
{
$http.get(API_ENDPOINT.url + '/listing/' + adId, {
params: {
page: page,
type: type // essentially $scope.type
},
});
typeWatcher = type;
}
};
You can wrap your get call in a function & call it after the filter function in ng-click
$scope.functionName = function () {
return $http.get(API_ENDPOINT.url + '/listing/' + adId, {
params: {
page: page,
type: type // essentially $scope.type
}
})
}
then in HTML
<button ng-click="filter('2'); functionName()"></button>
Well, To call $http.get method on click,
$scope.filter = function(type) {
if(type) {
//call the method using service.methodName
return type;
}
return '' ;
}
and wrap that $http.get method to one function.
Hope it helps you.
Cheers

How to recompile a widget's templateUrl in Malhar AngularJS dashboard framework

I'm using the Malhar AngularJS Dashboard Framework located here on github: https://github.com/DataTorrent/malhar-angular-dashboard , and a simple demo here: http://datatorrent.github.io/malhar-angular-dashboard/#/ .
Their system uses JQuery Sortable Widgets, which allows me to load up some charts and grids into a dashboard.
The way I load my charts and grids is by using their templateUrl property on the widget definition, as follows :
{
name: myWidgetEnum.TREELIST,
title: 'Tree List',
templateUrl: 'app/shared/gadget-templates/tree-list.html'
}
Here's a more complete sample of the Malhar Widget Definitions, which is where I define my UI "gadgets" to be rendered within the sortable widgets :
(function () {
'use strict';
angular.module('rage')
.factory('widgetDefinitions', ['ColumnChartDataModel', 'TreeListDataModel', 'TreeMapDataModel', 'GridDataModel', widgetDefinitions])
var myWidgetEnum = Object.freeze({
TREELIST: 'chart_treelist',
TREEMAP: 'chart_treemap',
HEATMAP: 'chart_heatmap',
GRID: 'chart_grid'
});
/* Define the widget definitions - base properties are defined in WidgetModel factory.
*/
function widgetDefinitions(ColumnChartDataModel, TreeListDataModel, TreeMapDataModel, GridDataModel) {
var size = { width: '20%', height: 90 };
var fixedSize = { width: '50%', height: 320 }; // keep height as a number, and add 'px' in directive
var initImagePath = 'images4/256x256/';
return [
{
name: myWidgetEnum.TREELIST,
title: 'Tree List',
templateUrl: 'app/shared/gadget-templates/tree-list.html',
dataModelType: TreeListDataModel,
dataModelOptions: {}, // this property will be persisted in DashboardState factory
gadgetType: 'table',
chartType: 'treelist',
settingsModalOptions: { }
},
{
name: myWidgetEnum.HEATMAP,
title: 'Heat Map',
templateUrl: 'app/shared/gadget-templates/grid.html',
dataModelType: GridDataModel,
dataModelOptions: {}, // this property will be persisted in DashboardState factory
gadgetType: 'table',
chartType: 'heatmap',
settingsModalOptions: {} // see 'MainCtrl' controller
}
];
}
})();
And the dashboard options in my main controller :
$scope.dashboardOptions = {
widgetButtons: false, // 'false' makes it a dropdown of options
widgetDefinitions: widgetDefinitions, // see dashboard-widget-factory.js
defaultWidgets: defaultWidgets,
storage: $window.localStorage,
storageId: $scope.defaultDashboardId, // 'rage.ui' - no longer hard code the storage Id - 06/11/2015 BM:
hideWidgetSettings: false,
settingsModalOptions: {
templateUrl: 'app/shared/include/gadget-config-new/gadget-config-container.html',
controller: 'GadgetSettingsCtrl_NEW as settings',
backdrop: true
},
onSettingsClose: function (result, widget) {
jQuery.extend(true, widget, result);
widget.dataModelOptions = result.dataModelOptions;
},
onSettingsDismiss: function (reason) {
console.log('widget settings were dismissed. Reason: ', reason);
}
};
When Malhar first loads up the widgets, it compiles the templateUrl within the JQuery sortable widget.
However, if I launch the widget settings modal and choose a different "widget" from the Widget Definitions list, I'm having an issue when I try to recompile the new templateUrl.
In other words if the first widget loaded up is the TREELIST, then in it's modal settings I choose a new widget called HEATMAP, I need to somehow force a recompile on the new html template that was loaded by Malhar.
Here on github, you can find the main directive, malhar-angular-dashboard.js https://github.com/DataTorrent/malhar-angular-dashboard/blob/master/dist/malhar-angular-dashboard.js , and if you search down for the 'DashboardWidgetCtrl' controller you'll find the $scope.makeTemplateString function as well as the $scope.compileTemplate function further below that.
I'm experimenting with the resolve section of the $modal instance as follows, but this seems to be more of a hack than an elegant solution:
See the angular.element below inside the try...catch section :
// Set resolve and reject callbacks for the result promise
modalInstance.result.then(
function (result) {
// Call the close callback
onClose(result, widget, scope);
// CHECK IF FIRST TIME CONFIGURING THE GADGET - 04/22/2015 BM:
if (!widget.gadgetConfigured) {
widget.gadgetConfigured = true;
widget.setHeight(widget.fixedSize.height);
widget.setWidth(widget.fixedSize.width);
}
scope.$broadcast('widgetSettingsClosed', widget, result);
//AW Persist title change from options editor
scope.$emit('widgetChanged', widget);
// hack to recompile the widget if user has swapped gadget types in gadget config modal - 10/01/2015 BM:
if (widget.chartType == "heatmap" || widget.chartType == "treelist") {
try {
angular.element(document.getElementById('dash')).scope().$$childHead.compileTemplate();
} catch (e) {
console.log("In modalInstance.result.then, cannot compile template " + e);
}
}
},
function (reason) {
// Call the dismiss callback
onDismiss(reason, scope);
}
);
If there's anyone with experience in Mahlar Dashboard, or in compiling directives, I would appreciate any guidance in this area.
thank you,
Bob

how to select current item in kendo dropdownlist using angularjs controller?

I am using the Kendo Drop Down List with Angular. Actually i want to select current items, which means i will choose one item from partial page, it will redirect to some other page, in that page i have to select that item dynamically.
HTML Code:
<select id="controltype" kendo-drop-down-list k-options="controlDatas">/select>
Angular Code:
$scope.objectModification=function(objectData) {
$scope.objectDataFields = objectData;
var objectViewPartialElement = angular.element("objectViewPartial");
objectViewPartialElement.html("");
$compile(objectViewPartialElement)($scope);
$http({
url : './resources/staticPages/object-modification.html',
method : "GET"
}).success(function(data, status) {
$scope.data = data;
jQuery("objectViewPartial").html($compile($scope.data)($scope));
}).error(function(data, status) {
console.log("some error occured partial page");
});
// This code i am using for that selection
$("#controltype").data("kendoDropDownList").select(function(dataItem) {
return dataItem.objectId === objectDataFields.objectId;
$("#controltype").data("kendoDropDownList").refresh();
});
};
I got solution for that in some other way. i placed my code inside of kendo controls event.
$scope.controlDatas = {
dataSource: controlDatas,
dataTextField: "controlName",
dataValueField: "attributeId",
dataBound: function(e) {
$("#controltype").data("kendoDropDownList").select(function(dataItem) {
return dataItem.attributeId===$scope.objectDataFields.attributeId;
$("#controltype").data("kendoDropDownList").refresh();
});
}
};

Resources