I have to create a 2 column form where left and right side will have different sections/groups of elements. these sections are created as directives, now i have to place these directives in the form based on the column and postion values that I recieve from the json.
{ group:"Group 1",column:1,position:2} then group1 directive should be placed on left side and in the second row of the left column. kindly suggest how to stitch these directives based on the position received
You can arrange your directives on the DOM as you want.
If you don't want to change elements on your DOM, You can create a directive with "C" or "A" as the required attribute (which means you can add it to any html element). Then, all you have to do is change the classes/ attribute on each position to get the desired result.
.directive('InputA', function () {
return {
restrict: 'C',
template... });
.directive('InputB', function () {
return {
restrict: 'C',
template... });
Then, your section can be like this:
<div col-m-6><div class="InputA"/><div class="InputB"/><div class="InputC"/></div>
than if you want to change the order all you have to do is change the classes to :
<div col-m-6><div class="InputC"/><div class="InputA"/><div class="InputB"/></div>
see http://jsfiddle.net/zmvr4tee/ - although i wouldn't recommend using jquery for the manipulation, i would create a parent directive that handles it but you get the idea.
Update:
added a function that recieveing a JSON, ordering it and place it according to column/position attributes.
function build(){
//you can play with column and position attributes to get different order
//recieving the JSON
var inputs = angular.fromJson('[{ "label": "firstThird","column":1,"position":3},{ "label": "secondSecond","column":2,"position":2},{ "label": "firstSecond","column":1,"position":2},{ "label": "secondThird","column":2,"position":3},{ "label": "firstFirst","column":1,"position":1},{ "label": "secondFirst","column":2,"position":1}]' );
//sorting the input to match the right postition of each directive
inputs.sort(function(a, b){
return (a.column*2+a.position)-(b.column*2+b.position);
});
//positioning the directives according to their column and postiion attributes
for(var i=0;i<3;i++)
{
$("#leftSection").children(':nth-child('+(i+1)+')').addClass(inputs[i].label);
}
for(var i=0;i<3;i++)
{
$("#rightSection").children(':nth-child('+(i+1)+')').addClass(inputs[i+3].label);
}
//compileing the form with angular to get the results
angular.element($("#myForm")).injector().invoke(function($compile) {
var scope = angular.element($("#myForm")).scope();
$compile($("#myForm"))(scope);
});
}
see update Fiddle here:Updated Fiddle
Related
I have a a web page where various fields are shown or hidden by toggling between "display:block" and "display:none". However, I added some extra stuff to the page and discovered that I needed to special-case several tags: TD needs to use "display:table-cell:, TR needs to use "display:table-row", and so on...
Is there any general off-the-shelf solution to this (i.e. look up the "natural" display type based on the tag name) or am I stuck with creating a JS object by hand which lists tag names and the corresponding display types?
You can apply revert to display property to set the element to it's original value and get the original value by Javascript.
const getOriginalDisplayProperty = (elem) => {
const modifiedDisplayProperty = getDisplayProperty(elem); //store modified display property
elem.style.display = "revert"; //revert to original display property
setTimeout(() => {
elem.style.display = modifiedDisplayProperty; // Again set original display property
}, 0);
return getDisplayProperty(elem);
};
const getDisplayProperty = (elem) =>
window.getComputedStyle(elem, null).display;
getOriginalDisplayProperty(document.querySelector(".test"));
getOriginalDisplayProperty(document.querySelector(".test-span"));
div {
display: inline;
}
span {
display: flex;
}
<div class="test"></div>
<span class="test-span"></span>
I have a datatable with a button to export its data to a pdf file using pdfmake. So far so good until I received the request to add one more value to one of the columns (and this value should not appear in the exported data). The column I'm having this problem has the following composition:
<td>{{client.lot}}<br><p>{{client.lot.total_negotiations}} client(s) negotiating!</p></td>
(Ok, I know this is not the best way to split all cells of the column into two rows)
What I'm trying to do is to export the data only with the "first row" (before the <br> tag). How can I accomplish this? There's any workaround adjusting the table or the pdf?
You can use the exportOptions.format() function provided by DataTables to do this.
For example, assuming we start with the following table data (where there are 2 cells containing data which needs to be formatted):
Then the resulting PDF will look as follows:
The DataTables configuration for this is:
$(document).ready(function() {
$('#example').DataTable( {
"dom": 'B<"clear">lfrtip',
buttons: [{
extend: 'pdf',
text: 'Save as PDF',
exportOptions: {
modifier: {
page: 'current'
},
format: {
body: function ( data, rowIdx, colIdx ) {
if (colIdx == 1) {
var brIdx = data.indexOf("<br>");
if (brIdx >= 0) {
return data.substring(0, brIdx);
} else {
return data;
}
} else {
return data;
}
}
}
}
}]
} );
} );
This uses a function to inspect the contents of each cell. In my case, I ignore any data which is not in column index 1 (the 2nd column in the table).
For each cell of data in this column, I check for the existence of a <br> tag in the data. If one exists, then all data from this tag to the end of the string is discarded.
All other cells in all other columns are passed through to the PDF unchanged.
You may need to adjust this, depending on your specific needs (e.g. if you need to handle multiple columns, maybe to clean up that trailing hyphen in "Lote 14 -", etc.).
You may want move the export logic to its own separate function, as well, and then call that function from the DataTable config instead (so the logic does not clutter the DataTable configuration code).
Background information on this export function can be found here: exportData - specifically, see the format section on that page. This is the general buttons function used by the exportOptions configuration in the above example.
This is the code snippet but I'm not able to understand how the observer method is working
static get properties() {
return {
selected: {
type: Object,
observer: '_selectedChanged'
}
};
}
_selectedChanged(selected, oldSelected) {
if (oldSelected) oldSelected.removeAttribute('selected');
if (selected) selected.setAttribute('selected', '');
}
connectedCallback() {
super.connectedCallback();
this.selected = this.firstElementChild;
}
full code: https://codelabs.developers.google.com/codelabs/polymer-2-carousel/index.html?index=..%2F..%2Findex#3
What is selected and oldselected and how can we do oldSelected.removerAttribute?
Are these objects of elements?
Please elaborate!
selected is property of element. It's value is some HTML element (in this case it's always img i think) so, in selected property there is always saved reference to img somewhere in html. When this property change, function _selectedChanged is called with 2 arguments. first argument is new image that is currently saved in selected and second argument is old image(previous value of selected).
further in tutorial you can see code
const elem = this.selected.nextElementSibling;
if (elem) {
this.selected = elem;
}
where is shown that const elem takes some html element and put it into this.selected.
So inside function _selectedChanged they removed html attribute from old image that was previously selected (so it was visible on screen) and added new html attribute to new image that should be visible on screen for now.
You can imagine that img with attribute selected is the only one that is shown on the screen at the time
I hope you understand my explanation. My english isn't 100% so if you have question, ask me and i can try to explain it more.
EDIT
Some example with binding and observer:
Let's say we have some paper-input which should show some results (articles for example) based on value of this input. So we have some HTML:
<paper-input value="{{search}}" label="Find articles"></paper-input>
this is primitive. Just some paper-input with value stored in search property. inside script tag:
Polymer({
is: 'test-el',
properties: {
search: {
type: String,
observer: "_findResults"
},
articles: {
type: Array
}
},
_findResults() {
this.set("articles", ['firstArticle', 'secondArticle', Math.random()]);
},
});
Explain: we defined property search and articles. Whenever property search changes, it calls function _findResults (because of observer). Function _findResults do only one thing. this.set("articles") is almost same as this.articles =. More about this can be found in documentation. So this.set("articles", ['firstArticle', 'secondArticle', Math.random()]); means it creates array and set it to articles property. and now, when we have some array that is changing everytime user enter some value in paper-input, we can add some HTML to show these articles:
<template is="dom-repeat" items="{{articles}}" as="item">
[[item]] <br>
</template>
I made also fiddle, so you can play with it and understand it a little bit more.
https://jsfiddle.net/2va41sy0/1/
Your question at the beginning was almost same in difference that they stored in some property reference to HTML object and not only just string. This is also about understand some basics of javascript and not polymer
I would like to get all child labels of a given parent label. Is it possible?
In How to check if a Gmail label has a nested sub-label? it is checked whether all labels have a sub-label, and I tried doing something similar for an specific one, but with no results.
The parent-child relation of Gmail labels is based on their names: it you have a label "foo/bar" and there is also a label named "foo", then the former is considered a child of the latter. (I just tested this by manually creating "foo/bar" label and then "foo"; as soon as "foo" appeared, it acquired "bar" as a child.)
So, the following function will return the list of all labels that are children of the given label. (The argument parent here is a label itself, not its name).
function children(parent) {
var name = parent.getName() + '/';
return GmailApp.getUserLabels().filter(function(label) {
return label.getName().slice(0, name.length) == name;
});
}
This question is similiar to them one asked in Mike's post Using ng-model within a directive.
I am writing a page which is small spreadsheet that displays calculated output based on user input fields. Using a directive, I'm making custom tags like this:
<wbcalc item="var1" title="Variable 1" type="input"></wbcalc>
<wbcalc item="var2" title="Variable 2" type="input"></wbcalc>
<wbcalc item="calc" title="Calculation" type="calc"></wbcalc>
The 'item' field references scoped data in my controller:
$scope.var1 = '5'; // pre-entered input
$scope.var2 = '10'; // pre-entered input
$scope.calc = function() {
return parseInt($scope.var1) + parseInt($scope.var2);
};
And the 'type' field is used in the directive's logic to know whether to treat the item as a string or a function.
Here's a fiddle for this: http://jsfiddle.net/gregsandell/PTkms/3/ I can get the output elements to work with the astonishing line of code:
html.append(angular.element("<span>")
.html(scope.$eval(attrs.item + "()"))
);
...and I'm using this to get my inputs connected to my scoped controller data (I got this from Mike's post:
var input = angular.element("<input>").attr("ng-model", attrs.item);
$compile(input)(scope);
html.append(input);
...while it does put the values in the fields, they aren't bound to the calculation, as you can see by changing inputs in my fiddle.
Is there a better and/or more intuitive way to link my controller-scoped data to the jqlite-generated html in my directive?
Take a look at this, I think you can simplify the process a fair bit.
http://jsfiddle.net/PTkms/4/
angular.module('calculator', []).directive('wbcalc', function($compile) {
return {
restrict: 'E',
template: '<div><div class="span2">{{title}}</div><input ng-model="item"></div>',
scope: {
title: '#',
item: '='
},
link: function(scope, element, attrs) {
// Don't need to do this.
}
}
});
function calcCtrl($scope) {
$scope.var1 = '5';
$scope.var2 = '10';
$scope.calc = function() {
// Yes, this is a very simple calculation which could
// have been handled in the html with {{0 + var1 + var2}}.
// But in the real app the calculations will be more
// complicated formulae that don't belong in the html.
return parseInt($scope.var1) + parseInt($scope.var2);
};
}
I know you said you like jQuery - but to make best use of Angular you need to think in an Angular way - use bindings, don't manipulate the DOM directly etc.
For this example, it would be helpful to read up on the isolated scope bindings used - '#' and '=', see:
http://docs.angularjs.org/guide/directive