I'm trying to use this Bootstrap Datetime Picker (version 4.17.37) inside a Backgrid cell, but I'm having a problem with the way the widget is rendering. The widget appears as a thin popup right below the cell, but seems to have no content inside. However, if you log the widget's inner html to the console, the content is there. It seems to me that there is something unusual going on inside the place function of the datetime picker, shown here.
This is my code for the custom Backgrid cell and its editor.
// Editor for the datetime picker cell.
var DatetimePickerCellEditor = Backgrid.InputCellEditor.extend({
events: {},
initialize: function() {
Backgrid.InputCellEditor.prototype.initialize.apply(this, arguments);
var input = this;
var timezone = 'America/Lima',
format = 'YYYY-MM-DD HH:mm';
this.$el.datetimepicker({
format: format,
timeZone: timezone
}).on('dp.show', function(event) {
event.preventDefault();
var column = input.column.get('name'),
date = input.model.get(column);
input.$el.data("DateTimePicker").date(date);
}).on('dp.hide', function(event) {
event.preventDefault();
var dateObj = event.date,
dateLocal = null;
if (dateObj) {
var dateString = dateObj.format(format);
dateLocal = moment.tz(dateString, timezone);
}
var command = new Backgrid.Command({}),
column = input.column.get("name");
// Save date in model as string in local time.
input.model.set(column, dateLocal.format());
input.model.trigger("backgrid:edited",
input.model,
input.column,
command);
command = input = null;
}).on('dp.error', function(error) {
console.log(error)
});
}
});
// Cell to display the datetime picker.
var DatetimePickerCell = Backgrid.Cell.extend({
editor: DatetimePickerCellEditor
});
This produces the following result:
Upon inspection, the element that the datetime picker was using as a parent is an ancestor <div class="col-lg-12 col-md-12">. I then tried to solve the problem by giving the cell a { position: relative } CSS property. That indeed made the datetime picker use the cell as a parent, but produced the following result visually:
You can see that the picker appears to be below the cell, but is not visible.
Playing around with other properties, such as widgetParent and widgetPositioning gave similar results.
I had same problem.
(I know that this is an old question, but I use backbone/backgrid today. I have a lot of additional issues with angular, vue or react on data grids, I find that this combo is the best, and simplest, until these days).
well, You only must add this after backbone/backgrid css to your th, td containers.
.backgrid th,
.backgrid td {
display: table-cell;
position: relative;
overflow: visible;
}
I use it in an backbone/backgrid project and it works perfect.
It's incredible, there is and display: none style overrrided, but, for any reason it continues makeing this fail.
I hope this could help some one else.
one capture:
Related
I have a problem in AngularJS + TS when it comes to refreshing the data and axis in Kendo chart.
There are 3 problems:
.refresh() and .redraw() didn't exist,
Data not refreshing,
Category Axis (X axis) not refreshing.
How to be able to use .refresh() etc. and then be able to change both data & X axis, when a new data is pushed?
I was dealing with it for few days (as a Junior BACKEND dev...), so I want to share my solution with you :)
TypeScript
First, you need to do "helper" field called "chart", with Partial to properly deal with optional ('myField?').
Probably you've got just .ChartOptions,
chartOptions: kendo.dataviz.ui.ChartOptions;
but only .Chart has .refresh() method, so create new field called chart:
chart: Partial<kendo.dataviz.ui.Chart>;
and in the initialization method of your chart, do an observable from dataSource in your chartOptions:
this.chartOptions = {
// Other fields of the chartOptions
dataSource: new kendo.data.DataSource({
transport: {
read: (options) => {
// Your logic to create new data array
options.success(yourNewData);
}
}})
};
}
and then create new method (refresh), that should look like this:
this.chartOptions.dataSource.read();
'labels' in this.chart.options.categoryAxis ? this.chart.options.categoryAxis.labels.step = step : null;
this.chart.refresh();
HTML:
(remember to set options from chartOptions, not .chart.options, because you cannot get options from non-existing object.)
<div>
<div kendo-chart="$ctrl.chart" k-options="$ctrl.chartOptions"></div>
</div>
Also remember, when you close your chart (eg. by ng-if), then you need to run init function again, because refresh function would throw an error about "undefined".
I am using fullcalendar with react. I am trying to customize the dayGrid view. According to the Content Injection docs for react I can use custom content for the rendering of both the date and the header cells. The dayCellContent "hook" states that:
Generated content is inserted inside the inner-most wrapper of the day cell. It does not replace the cell.
I've provided an implementation for the dayCellContent and noticed that my content gets injected into the following structure:
<td class="fc-daygrid-day fc-day fc-day-wed fc-day-past rot_time-off_day-cell" data-date="2021-04-07">
<div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner">
<div class="fc-daygrid-day-top">
<a class="fc-daygrid-day-number">
...custom content goes here
</a>
</div>
<div class="fc-daygrid-day-events"></div>
<div class="fc-daygrid-day-bg"></div>
</div>
</td>
Now, the problem is that this structure lets you insert content ONLY in the upper right corner of the date cell due to the positioning of the element. Furthermore, it is in an anchor element.
Example:
function renderDayCell(dayCellContent: DayCellContentArg) {
return (
<div>
{dayCellContent.dayNumberText}
</div>
);
}
Is there a clean way to customize the whole content of the cell somehow? I've seen a couple of sites using fullcalendar that have their content inserted directly into the td. Not sure if this is version dependent or they're using the alternative JS approach based on domNodes or html. I am using version 5.6.0 of fullcalendar.
I had the same requirement although not using React. I solved it using a manual manipulation of the DOM elements as suggested above. I have used jQuery for the select and manipulation. It is posted here in case anyone would like to see an example of how this can be achieved using DOM manipulation.
I implemented dayCellContent to make the day-cell DOM element easily identifiable by wrapping it in a span, with a unique id attribute based on the day of year number:
dayCellContent: function(info, create) {
const element = create('span', { id: "fc-day-span-"+info.date.getDayOfYear() }, info.dayNumberText);
return element;
},
This dayCellContent implementation makes no visible difference to the calendar but makes it easier to identify the elements to be modified in the DOM.
I then implemented dayCellDidMount to do the DOM manipulation by finding the appropriate cells and selecting their parent’s parent:
dayCellDidMount: function(info) {
let element = "<div style='position: absolute; left: 4px; top: 4px;'><a href='https://www.w3schools.com/'>TEST-"+info.dayNumberText+"</a></div>";
$('#fc-day-span-'+info.date.getDayOfYear()).parent().parent().prepend(element);
},
In this case I have just put a link to w3c in the top left of the cell with test text which also includes the day number. It results in cells that look like this:
Clearly the CSS could be improved and should be moved out to the CSS definitions but it illustrates the point.
Warning: This approach makes assumptions about the DOM structure that FullCalendar generates. The generated HTML may change in future versions of the product which could invalidate it. If you go this way then be careful when doing a FullCalendar update.
Note that the getDayOfYear function is from the ext-all.js library. Any way of uniquely identifying the day will work.
ngAfterViewInit(){
// Your CSS as text
var styles =.fc td, .fc th { vertical-align: top; padding: 0; height: 100px; } a{ color:#3d1cba; }
let styleSheet = document.createElement("style");
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
let arrTD = document.querySelectorAll('td.fc-timeline-slot');
let arrTR= document.querySelectorAll('td.fc-timeline-lane.fc-resource');
let arrInject= document.querySelectorAll('td.fc-timeline-lane.fc-resource>div.fc-timeline-lane-frame');
console.log(arrTR);
let k=-1;
arrTR.forEach(eachTR => {
let i=1;
let str = '';
k++;
let data_resource_id= eachTR.getAttribute('data-resource-id');
console.log(data_resource_id);
arrTD.forEach(eachTD => {
let k=100*(i-1);
i=i+1;
let data_date= eachTD.getAttribute('data-date');
console.log(data_date);
let data_resource_id= eachTR.getAttribute('data-resource-id');
console.log(data_resource_id);
str = str + '<span data-date="'+data_date+'" data-resource-id="'+data_resource_id+'" class="plus_icon" style="position:relative;top: 0px; left: '+k+'px !important;width:500px;height:500px;z-index:3;-moz-border-radius:100px;border:1px solid #ddd;-moz-box-shadow: 0px 0px 8px #fff;">+</span>';
});
arrInject[k].innerHTML=str;
});
let elementList = this.elRef.nativeElement.querySelectorAll('span.plus_icon');
for(let i=0;i<elementList.length;i++){
elementList[i].addEventListener('click', this.plusClick.bind(this));
}
}
I got a json response like this. It is dynamic and I want to add the details in range slider. The slider max value must dynamically increases when there will be new element in array.
"time": [
"2018-05-24T06:30:00",
"2018-05-24T07:00:00",
"2018-05-24T07:30:00"
]
I have never worked on slider before . Any suggestion how to achieve this ?
You can use angularjs-slider library (which has ui-bootstrap as dependency). It offers lot customization in sliders & very handy with angularjs.
For your case after every new value added to array you can reload the slider by 1st deleting it & then loading it again. Or you can use their rzSliderForceRender custom event for that. Using this
Your HTML will look like:
<rzslider rz-slider-model="slider_dates.value"
rz-slider-options="slider_dates.options"></rzslider>
And in controller slider config code as:
$scope.dates = ["2018-05-24T06:30:00",
"2018-05-24T07:00:00"];
var datesObjests = [];
for (var i = 0; i < $scope.dates.length; i++) {
datesObjests.push(new Date($scope.dates[i]));
}
$scope.slider_dates = {
value: datesObjests[0],
options: {
stepsArray: datesObjests,
translate: function(date) {
if (date !== null) return date.toLocaleString();
return '';
},
},
};
Working Plunker Example for your requirement.
i try to get the the value of number row selected, and print it in HTML using Angularjs, but no issue,
i have the count only when i clic in the grid column header.
The value of " selectedRowsCounter " is 0 in html, when i dosn't clic in the grid header
my code is like
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
};
$scope.gridOptions = {
rowData: null,
angularCompileRows: true,
onSelectionChanged: activeButtons,
}
there is a screenshot
i have open the same subject here
https://github.com/ceolter/ag-grid/issues/1023
i have added this line to activeButtons function and it work fine
$scope.gridOptions.api.refreshView();
i dont knew if there is a good solution, but that work for now
The problem seems to be with Angular being unaware of the $scope property change because ag-grid does not tell Angular that it has modified something in the $scope. Although it is difficult to tell if you don't show your view.
You can use onSelectionChanged the way you are using it to know how many rows have been selected, but you need to tell Angular that something has changed in its $scope by applying it.
Something like this:
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
window.setTimeout(function() {
this.$scope.$apply();
});
};
That way you can apply the $scope and the html view will reflect the changes.
I'm new to extjs and I'm looking for a way to add some custom message under my combobox field.
Depending on some conditions (eg. value selected) the message needs to have different text and/or style.
I could play with errorEl associated with my combobox and change it's message/style depending on the state, but this doesnt look like a good approach.
Are you aware of any plugin allowing to add such a message, or is there a shorter way to do this?
Thank you for your suggestions. I ended up writing my own plugin, which then I attached to combobox.
I added new element after error element and I changed messages based on proper combobox events.
afterCmpRender : function() {
var me = this, cmp = me.getCmp();
var messageWrapper = {
tag : 'div'
};
var messageEl = cmp.errorEl.insertSibling(messageWrapper, "after");
cmp.messageEl = messageEl;
Ext.Array.each(me.messages, function(message) {
var messageConfig = {
tag : 'div',
style : {
display : 'none'
}
};
var newElement = messageEl.insertSibling(messageConfig, "after");
newElement.setHTML(message.value);
newElement.addCls(message.classes);
me.registerMessageEvents(me, cmp, message, newElement);
});
}
I almost always use multiple elements for this, and would not make an attempt to change the field.
Depending on your context, which you didn't provide, I'd say you could have a look at:
Ext.form.field.Display
Ext.form.Label
Ext.tip.Tip
Ext.tip.QuickTip
I'd work with the class Ext.tip.Tip.
You can create
Ext.create('Ext.tip.Tip', {
id: 'myTip',
header: false
});
and then
var tip = Ext.getCmp('myTip');
tip.update('your custom tip message');
tip.showBy(comboboxComponent);
You could also use showAt(..) instead of showBy.
For more information look into the Docu
Here is a Fiddle link to an example.