I have a hard time figuring out what to do in my AngularJs single-page . I use ng-repeat to display a number of widgets. The plugin is "Jarvis widget v2.0". My problem is, that the article container does not have the functionality from the Jarvis widget (fullscreen, collapse etc.).
The data is delayed because of a HTTP GET call. If I hard-code the dataSeries it works 100%, but it seems that the Jarvis widgets gets rendered before the success of the HTTP GET. I have tried to find a solution for days and my guess is that a directive is the solution, but I'm lost!
<article class="col-xs-12 col-sm-12 col-md-6 col-lg-6" ng-repeat="chart in dataSeries">
<div class="jarviswidget" id="wid-id-02" data-widget-editbutton="false" data-widget-colorbutton="false" data-widget-deletebutton="false"></div>
</article>
This is my first post, so if I forgot something i apologize in advance.
The code inside function setup_widgets_desktop() is going to create the widgets based on the current(!) HTML content. As ng-repeat will render your element after you have a success from your HTTP request, there are no elements present when the function is called.
In order to achieve the behaviour you want, execute setup_widgets_desktop() again after your callback returns. You might need to make sure it is delayed by using $timeout(setup_widgets_desktop, 1000). I am using it this way, but not sure if it is a general requirement to have a delay.
The best option would be to extract the call $('#widget-grid').jarvisWidgets() into an directive. You could replace $('#widget-grid') with getting the current $(element), so it is only bound to the current element and not some fixed ID inside the DOM. If you need more advice on this, just drop me a line.
Edit (sample code):
In my project I am using the following Angular service (you have to replace yourApp, the HTTP URI and the jQuery selector to your needs):
(function(yourApp) {
"use strict";
yourApp.factory("presenter", function ($timeout) {
var layout = function () {
$("#widgets-grid").jarvisWidgets({
grid: "article",
widgets: '.jarviswidget',
localStorage: false,
// deleteSettingsKey: '#deletesettingskey-options',
// settingsKeyLabel: 'Reset settings?',
// deletePositionKey: '#deletepositionkey-options',
// positionKeyLabel: 'Reset position?',
sortable: false,
buttonsHidden: false,
// toggle button
toggleButton: false,
toggleClass: 'fa fa-minus | fa fa-plus',
toggleSpeed: 200,
onToggle: function () {
},
// delete btn
deleteButton: false,
deleteClass: 'fa fa-times',
deleteSpeed: 200,
onDelete: function () {
},
// edit btn
editButton: false,
editPlaceholder: '.jarviswidget-editbox',
editClass: 'fa fa-cog | fa fa-save',
editSpeed: 200,
onEdit: function () {
},
colorButton: false,
// full screen
fullscreenButton: true,
fullscreenClass: 'fa fa-expand | fa fa-compress',
fullscreenDiff: 3,
onFullscreen: function (e) {
},
// order
buttonOrder: '%refresh% %custom% %edit% %toggle% %fullscreen% %delete%',
opacity: 1.0,
dragHandle: '> header',
placeholderClass: 'jarviswidget-placeholder',
indicator: true,
indicatorTime: 600,
ajax: true,
timestampPlaceholder: '.jarviswidget-timestamp',
timestampFormat: 'Last update: %m%/%d%/%y% %h%:%i%:%s%',
refreshButton: true,
refreshButtonClass: 'fa fa-refresh',
labelError: 'Sorry but there was a error:',
labelUpdated: 'Last Update:',
labelRefresh: 'Refresh',
labelDelete: 'Delete widget:',
afterLoad: function () {
},
rtl: false, // best not to toggle this!
onChange: function () {
},
onSave: function () {
},
ajaxnav: $.navAsAjax // declears how the localstorage should be saved
});
}
return {
layout: function() {
$timeout(layout, 1000);
}
};
});
})(window.yourApp);
Your controller should then look like this:
function($scope, $http, presenter) {
...
$http("api/data").success(function(data) {
$scope.dataSeries= data;
presenter.layout();
});
...
}
OK, with help from Darneas I came up with a solution.
I implemented this:
: Calling a function when ng-repeat has finished
I made sure that "widget-grid" wasn't initialized (I had some test widgets)
I called "setup_widgets_desktop()" from the ngRepeatFinished
This was succesfull. Thank you Darneas. I wouldn't had found a solution otherwise.
I couldn't get the widget directive to work, which looks like a great solution as well.
Related
I am using DyGraph from https://smartadmin-ng2.github.io/#/graphs/dygraphs. I want to control two dygraph with one showRangSelector. Right now both dygraph has own rang selector. But I want to control with one rang selector, Because both rang selector has same work. Show I want to show one screen shot for more understanding.
dygraphsNoRollTimestamp.js
angular.module('app.xyz').directive('dygraphsNoRollTimestamp', function (DygraphsDataDemo) {
return {
restrict: 'A',
compile: function () {
return {
post: function (scope, element) {
new Dygraph(element[0], DygraphsDataDemo.data_total_volume, {
customBars: true,
title: '',
ylabel: 'Total Volume',
legend: 'always',
labelsDivStyles: {
'textAlign': 'right'
},
showRangeSelector: true
});
}
}
}
}
});
dygraphsNoRollPeriod.js
'use strict';
angular.module('app.xyz').directive('dygraphsNoRollPeriod', function (DygraphsDataDemo) {
return {
restrict: 'A',
compile: function () {
return {
post: function (scope, element) {
new Dygraph(element[0], DygraphsDataDemo.data_temp, {
customBars: true,
title: '',
ylabel: 'Total Volume',
legend: 'always',
showRangeSelector: true
});
}
}
}
}
});
DygraphsDataDemo.js
angular.module('app.air').factory('directory', function(){
function data_temp() {
return "Date,NY,SF\n20070101,46;51;\n20070102,47;60;\n;\n20070102,90;38;\n";
}
function data_total_volume() {
return "Date,NY,SF\n20070101,26;91;\n20070102,27;30;\n;\n20070102,20;38;\n";
}
return {
data_temp: data_temp,
data_total_volume: data_total_volume
}
})
controller.js
angular.module('app.xyz').controller('dcontroller',function ($scope) {
});
index.html
<div jarvis-widget id="dygraphs-chart-1" data-widget-editbutton="false">
<div>
<div class="widget-body">
<div dygraphs-no-roll-period style="width: 100%;height: 300px;"></div>
</div>
<div class="widget-body">
<!-- this is what the user will see -->
<div dygraphs-no-roll-timestamp style="width: 100%;height: 300px;"></div>
</div>
</div>
So If You see the screen shot then u can see two dygraph has two timeselector(rang selector). So I want to control both dygraph by one rang selector.
I have seen one link (DYGraphs: Control multiple graphs with one RangeSelector I did not get solution.My question related to http://dygraphs.com/gallery/#g/range-selector. You can click jsfiddle button for code in this link. This question is important for me. Your answer will be very valuable for me.
If you want to control both graphs with the same range selector you have to synchronize the graphs like in this example of dygraphs documentation. When the graphs are synchronized, the range selectors displayed works for all the graphs synchronized, so you can use only one range selector or even both, but they are going to be linked.
To use this functionality you have to use the synchronizer.js. It´s easy to use, you only have to use the code below where gs is an array with the dygraphs you want to synchronize.
var sync = Dygraph.synchronize(gs, {
zoom: true,
selection: true,
range: false
});
I am not familiar with angular but I think it will be also work.
Try this synchronizer.js and tell us about your results. If you don´t get to make it work I will try to help you better when I have more time. Regards
I have setup a kendo grid. The gird has a column containing a hyperlink. When I click on the link, I need to call a function and then I need to redirect to a new page. I know it sounds simple. I have a stand alone example which is doing same.
But when I try to use same logic in kendo grid, I am unable to get the desired result. Please help. Here is a link to Kendo Grid with a column containing hyperlink.
$('#one').kendoGrid({
dataSource: dataOne,
columns: [{
field: 'a',
template: "<a onclick=return doWork() href='/home/again/${a}'>${a}</a>"
}, {
command: 'destroy'
}],
editable: {
confirmation: false
}
});
try this soution
Add this function before grid settings:
function showFoo() {
alert('I am foo!');
return true;
}
Add following code at the end (after grid settings).
var el = document.getElementById('foo');
el.onclick = showFoo;
You need prevent the default click by event.preventDefault() and then redirect.
$('#one').kendoGrid({
dataSource: dataOne,
columns: [{
field: 'a',
template: "<a onclick=\"doWork(event, '/home/again/${a}')\" href=''>${a}</a>"
}, {
command: 'destroy'
}],
editable: {
confirmation: false
}
});
function doWork(ev, url){
ev.preventDefault();
alert("redirecting");
//... do your works
window.location.href = url;
}
I have a DataTable displaying data for Branches with two custom buttons defined: Add and Update. They are initialized at the top of the Javascript section
var buttons;
var tblBranch;
$.fn.dataTable.ext.buttons.add = {
className: 'button-add',
text: "Add Branch",
action: function (dt) {
onBtnAddClicked()
}
};
$.fn.dataTable.ext.buttons.update = {
className: 'button-update',
text: "Update",
action: function (dt) {
onBtnUpdateClicked()
}
};
I'd like to disable the Edit button on page load and only enable it to be clickable when a row has been selected. Problem is, I'm using custom buttons and I can't find anything on datatables.net about how to enable/disable them depending on conditions. So far what I've tried is this:
tblBranch = $("#tblBranches").DataTable({
dom: 'Blfrtip',
buttons: {
buttons :[
'add', 'update'
]
}
select: true;
})
$("#tblBranches tbody").on('click', 'tr', function () {
if (tblBranch.row(this).hasClass('selected')) {
$('button-update').removeClass("DTTT_disabled");
}
else {
table.$('tr.selected').removeClass('selected');
$('button-update').addClass("DTTT_disabled");
}
});
But I don't know what the code to disable the Edit button when the page loads should be like, and I've looked here, here, here and here.
Thanks for any guidance.
The last link you are referring to hold the solution you are looking for. But the documentation is a little bit vague, guess it need a solid example. It is not clear how you create the buttons (you show both methods) but below is an inline example, it would work with constructor as well. Simply give the button a class, like .edit and set it to disabled from start :
var table = $('#example').DataTable( {
dom: 'Bfrtip',
select: true,
buttons: [
{
text: 'Edit',
className: 'edit',
enabled: false,
action: function (e, dt, node, config) {
//do something
}
},
{
text: 'Add',
action: function (e, dt, node, config) {
//do something
}
}
]
})
Then use the Select plugins select and deselect events to update the enabled status of the .edit button :
$('#example').on('select.dt deselect.dt', function() {
table.buttons( ['.edit'] ).enable(
table.rows( { selected: true } ).indexes().length === 0 ? false : true
)
})
demo -> https://jsfiddle.net/pmee6w2L/
I'm trying to use bootstrap-markdown and everything works fine except I can't call the plugin via JavaScript. For instance:
$("#content").markdownEditor({
autofocus: false,
savable: false,
iconlibrary: 'fa',
resize: 'vertical',
additionalButtons: custom_buttons, // an array defining custom commands
onPreview: function (e) {
var content = e.getContent();
console.log('content', content);
}
});
Does anyone has any ideas what might be the case? Couldn't find anything useful on the web or repo's github page. And yes I've already included markdown.js and to-markdown.js which weren't mentioned in the docs at all but it was quick find anyway.
All I need now is to call the editor, add a couple of custom toolbar buttons (image upload, code block insert etc.) and be done with it.
Code snippets, links & live fiddles are much appreciated :)
For some reason, changing the order of script references fixed this.
Here's the order now:
lib/markdown.js
lib/bootstrap-markdown.js ,
lib/to-markdown.js
And here's my initialization:
$(function () {
var custom_buttons = [[
{
name: "insertCode",
data: [{
name: "cmdInsertCode",
toggle: "toggle",
title: "Insert Code",
icon: "fa fa-fire",
callback: function (e) {
var selected = e.getSelection(),
content = e.getContent();
// e.replaceSelection(chunk);
// var cursor = selected.start;
//e.setSelection(cursor, cursor + chunk.length);
console.log('cmdInsertCode clicked');
}
}]
}
]];
$("#content").markdown({
autofocus: false,
savable: false,
iconlibrary: 'glyph',
resize: 'vertical',
additionalButtons: custom_buttons,
onShow: function (e) {
console.warn('e:editor shown');
}
});
});
Kudos :godmode:
I'm going to ask another newbie question. I have come across multiple ways for a child to reference functions and data defined at the parent class level, but I'm not sure what is the recommended way. Below is an example that I am dealing with, but this topic is generally important for me since I do not have a good understanding of reference and scope of parents and children. How can I reference functions and data of a parent from a child of a child element?
As usual, any help will be highly appreciated.
Mohammad
San Jose, CA
/******
This is a floating panel with a formpanel inside it, that has an email field and a button to process the email.
When the button is tapped, I want to call the processEmails() function from the button.
******/
Ext.define('myapp.view.ForwardPanel', {
extend : 'Ext.Panel',
xtype : 'forwardPanel',
initialize: function() {
this.callParent(arguments);
var btn = {
xtype: 'button',
ui: 'action',
text: 'Send',
listeners: {
tap: function(){
processEmails(); //<- **How can I reference and call this function?**
// This function is defined at the parent class level
// (indicated at the bottom of the code listing)
}}
};
var form = {
items: [{
xtype: 'fieldset',
instructions: 'Enter multiple emails separated by commas',
title: 'Forward this message.',
items: [ {
xtype: 'emailfield',
name: 'email',
label: 'Email(s)'
},btn] // The button is added to the form here
}]
};
this.add(form);
},
// this is the parent level function I want to call upon button tap.
processEmails: function(){
console.log('Processing email...');
}
});
I'm not sure about a "right" way to do it, but this is what I would do, and what I see most of the time in the Sencha forum and in their own code:
Ext.define('myapp.view.ForwardPanel', {
...
initialize: function() {
this.callParent(arguments);
var me = this; // <---- reference to the "ForwardPanel" instance
var btn = {
xtype: 'button',
ui: 'action',
text: 'Send',
listeners: {
tap: function(){
me.processEmails(); // <-- notice the "me" in front
}
}
};
...
},
// this is the parent level function I want to call upon button tap.
processEmails: function(){
console.log('Processing email...');
}
});
You can make use of prototype to achieve it:
myapp.view.MyView.prototype.processEmails.call(this);
Here is a working fiddle: http://www.senchafiddle.com/#MvABI