commit be19f89c74cf1456e5f6635f96347bb50a3024fb Author: sainw Date: Tue Aug 4 15:32:57 2026 +0630 first commit diff --git a/AccountMgr.md b/AccountMgr.md new file mode 100755 index 0000000..0263195 --- /dev/null +++ b/AccountMgr.md @@ -0,0 +1,29 @@ +## Install sshd +In order to enable ssh on Ubuntu Linux, we first need to perform an SSH package installation. Open up terminal and enter command: + + $ sudo apt install sshd + + + +## Create a user using command line +Let's start by creating a new user. Open up terminal and enter: + + $ sudo adduser --no-create-home username + + + +## Create non-login/system user +Let's start by creating a new user. Open up terminal and enter: + + $ sudo useradd -r username + + +## Change default shell + $ grep user /etc/passwd + + $ usermod --shell /bin/bash user + + $ grep user /etc/passwd + +## Adding User to the sudo Group + $ usermod -aG sudo username \ No newline at end of file diff --git a/Android.md b/Android.md new file mode 100644 index 0000000..f00d8b5 --- /dev/null +++ b/Android.md @@ -0,0 +1,12 @@ +# Remote debug android phone +### Set the target device to listen for a TCP/IP connection on port 5555 +``` +$adb -s device_id tcpip 5555 +``` + + +### Connect to the device by its IP address +``` +$adb connect device_ip_address +$adb devices +``` diff --git a/BashScriptFile.md b/BashScriptFile.md new file mode 100755 index 0000000..459663a --- /dev/null +++ b/BashScriptFile.md @@ -0,0 +1,19 @@ +## Basic bash script +``` +#!/bin/bash + +# declare STRING variable +STRING="Hello World" + +#print variable on a screen +echo $STRING +``` + +## Backup bash script + +``` +#!/bin/bash +tar -czf backup.tar.gz /home/app/data +``` + +[Bash Scripting Tutorial](https://linuxconfig.org/bash-scripting-tutorial) \ No newline at end of file diff --git a/CustomElements.md b/CustomElements.md new file mode 100755 index 0000000..3d95a4c --- /dev/null +++ b/CustomElements.md @@ -0,0 +1,487 @@ +# Custom element concepts + + To define a custom element, create a class that extends **PolymerElement** and pass the class to the **customElements.define** method.The custom element's name must start with a lower-case ASCII letter and must contain a dash (-). + + import {PolymerElement} from '@polymer/polymer/polymer-element.js'; + + export class MyPolymerElement extends PolymerElement { + ... + } + + customElements.define('my-polymer-element', MyPolymerElement); + + + +### Polymer element lifecycle + + + + Reaction Description + + + constructor -Called when the element is upgraded.The constructor is a logical place to setdefault values,and to manually set up event listeners for the element itself. + + connectedCallback -Called when the element is added to a document.Can be called multiple times during the lifetime of an element.Uses include adding document-level event listeners. + + disconnectedCallback -Called when the element is removed from a document. Can be called multiple times during the lifetime of an element.Uses include removing event listeners added in connectedCallback. + + ready -Called during Polymer-specific element initialization. Called once, the first time the element is attached to the document. + + attributeChangedCallback -Called when any of the element's attributes are changed, appended, removed, or replaced.Use to handle attribute changes that don't correspond to declared properties. + + + +### Polymer element initialization + + ready() { + super.ready(); + // do something that requires access to the shadow tree + ... + } + + The PolymerElement class initializes your element's template and data system during the **ready** callback, so if you override ready, you must call **super.ready()** before accessing the element's shadow tree. + + +### Defer non-critical work + + When possible, defer work until after first paint. The render-status module provides an "afterNextRender" utility for this purpose. + + import {PolymerElement} from '@polymer/polymer/polymer-element.js'; + import {afterNextRender} from '@polymer/polymer/lib/utils/render-status.js'; + + class DeferElement extends PolymerElement { + ... + constructor() { + super(); + // When possible, use afterNextRender to defer non-critical + // work until after first paint. + afterNextRender(this, function() { + this.addEventListener('click', this._handleClick); + }); + } + } + + +### Element upgrades + + Adding a definition for an element causes any existing instances of that element to be upgraded to the custom class. + + For example: + + + + +### Extending other elements + +In addition to PolymerElement, a custom element can extend another custom element: + + import {MyElment} from './my-element.js'; + + export class ExtendedElement extends MyElement { + + static get is() { return 'extended-element'; } + + .... + + }; + + customElements.define(ExtendedElement.is, ExtendedElement); + + +### Sharing code with class expression mixins + +A mixin is simply a function that takes a class and returns a subclass: + + MyMixin = function(superClass) { + return class extends superClass { + constructor() { + super(); + this.addEventListener('keypress', (e) => this._handlePress(e)); + } + .... + } + } + + + Or using an ES6 arrow function: + + MyMixin = (superClass) => class extends superClass { + ... + } + + + Add a mixin to your element like this: + + class MyElement extends MyMixin(PolymerElement) { + static get is() { return 'my-element' } + } + + +When creating a mixin that you intend to share with other groups or publish, a couple of additional steps are recommended: + + - Use the dedupingMixin function to produce a mixin that can only be applied once. + + - Define the mixin in an ES module and export it. + For Example, + + + class MyElement extends MixinB(MixinA(Polymer.Element)) { ... } + + +At this point, your element contains two copies of MixinB in its prototype chain. dedupingMixin takes a mixin function as an argument, and returns a new, deduplicating mixin function: + +mixin-b.js + + + import {dedupingMixin} from '@polymer/polymer/lib/utils/mixin.js'; + + // define the mixin + let internalMixinB = (base) => + class extends base { + ... + } + + // deduplicate and export it + export const MixinB = dedupingMixin(internalMixinB); + + + + +# Declare Properties + + Declared properties can specify: + + * Property type.Type: constructor + * Default value.Type: boolean, number, string or function. + * Property change observer. Calls a method whenever the property value changes.Type: string + * Read-only status. Prevents accidental changes to the property value.Type: boolean + * Two-way data binding support. Fires an event whenever the property value changes.Type: boolean + * Computed property. Dynamically calculates a value based on other properties.Type: string + * Property reflection to attribute. Updates the corresponding attribute value when the property value changes.Type: boolean + + +Example + + class XCustom extends PolymerElement { + + static get properties() { + return { + user: String, + isHappy: Boolean, + count: { + type: Number, + readOnly: true, + notify: true + } + } + } + } + + customElements.define('x-custom', XCustom); + + +### Property name to attribute name mapping + + When mapping attribute names to property names: + + -Attribute names are converted to lowercase property names. For example, the attribute "firstName" maps to "firstname". + + - Attribute names with dashes are converted to camelCase property names by capitalizing the character following each dash,then removing the dashes. For example, the attribute "first-name" maps to "firstName". + + +### Configuring object and array properties + + For object and array properties you can pass an object or array in JSON format: + + + + + +### Configuring default property values + Default values for properties may be specified in the properties object using the value field, or set imperatively in the element's constructor. + + + **Default in properties object** + + class XCustom extends PolymerElement { + + static get properties() { + return { + mode: { + type: String, + value: 'auto' + }, + + data: { + type: Object, + notify: true, + value: function() { return {}; } + } + } + } + } + + + +**Default in constructor** + + constructor() { + super(); + this.mode = 'auto'; + this.data = {}; + } + + static get properties() { + return { + mode: String, + + data: { + type: Object, + notify: true + } + } + } + + +### Property change notification events (notify) + +When a property is set to notify: true, an event is fired whenever the property value changes. The event name is: + + **property-name-changed** + +Where property-name is the dash-case version of the property name. For example, a change to **this.firstName** fires **first-name-changed**. + + + +### Read-only properties + +When a property only "produces" data and never consumes data, this can be made explicit to avoid accidental changes from the host by setting the readOnly flag to true in the properties property definition. In order for the element to actually change the value of the property, it must use a private generated setter of the convention **_setProperty(value)** where Property is the property name, with the first character converted to uppercase (if alphabetic). For example, the setter for **oneProperty** is **_setOneProperty**, and the setter for**_privateProperty** is **_set_privateProperty**. + + + class XCustom extends PolymerElement { + + static get properties() { + return { + response: { + type: Object, + readOnly: true, + notify: true + } + } + } + + responseHandler(response) { + // set read-only property + this._setResponse(response); + } + } + + +### Reflecting properties to attributes +In specific cases, it may be useful to keep an HTML attribute value in sync with a property value. This may be achieved by setting **reflectToAttribute: true **on a property in the properties configuration object. This causes any observable change to the property to trigger an update to the corresponding attribute.Since attributes only take string values, the property value is serialized to a string.For Example, + + class XCustom extends PolymerElement { + + static get properties() { + return { + loaded: { + type: Boolean, + reflectToAttribute: true + } + } + } + + _onLoad() { + this.loaded = true; + // results in this.setAttribute('loaded', true); + } + } + + + + + +### Custom deserializers + + The type system includes built-in support for Boolean and Number values, Object and Array values expressed as JSON, or Date objects expressed as any Date-parsable string representation. To support other types, you can override the element's **_deserializeValue** method. + + + _deserializeValue(value, type) { + if (type == MyCustomType) { + return stringToMyCustomType(value); + } else { + return super._deserializeValue(value, type); + } + } + + + + +### Attribute serialization + +When reflecting a property to an attribute or binding a property to an attribute, the property value is serialized to the attribute. + +By default, values are serialized according to value's current type, regardless of the property's type value: + +*String. No serialization required. +*Date or Number. Serialized using toString. +*Boolean. Results in a non-valued attribute to be either set (true) or removed (false). +*Array or Object. Serialized using JSON.stringify. + +To add custom serialization for other data types, override your element's **_serializeValue** method. + + _serializeValue(value) { + if (value instanceof MyCustomType) { + return value.toString(); + } + return super._serializeValue(value); + } + + + +### Define a legacy element + + Legacy elements can use use the Polymer function to register an element. The function takes as its argument the prototype for the new element. The prototype must have an is property that specifies the HTML tag name for your custom element.For Examples, + + // register an element + MyElement = Polymer({ + + is: 'my-element', + + // See below for lifecycle callbacks + created: function() { + this.textContent = 'My element!'; + } + + }); + + // create an instance with createElement: + var el1 = document.createElement('my-element'); + + // ... or with the constructor: + var el2 = new MyElement(); + + +### Legacy lifecycle callbacks + + + + legacy callback Description + + + created -Called when the element has been created, but before property values are set and local DOM is initialized.Use for one-time set-up before property values are set.Equivalent to the native constructor. + + + ready -Called after property values are set and local DOM is initialized.Use for one-time configuration of your component after its shadow DOM tree is initialized. + + attached -Called after the element is attached to the document. + + detached -Called after the element is detached from the document. + + attributeChanged -Called when one of the element's attributes is changed. + + + **Using legacy behaviors with class-style elements** + +You can add legacy behaviors to your class-style element using the mixinBehavior function: + + import {PolymerElement} from '@polymer/polymer/lib/legacy/class.js'; + import {mixinBehaviors} from '@polymer/polymer/polymer-element.js'; + + class XClass extends Polymer.mixinBehaviors([MyBehavior, MyBehavior2], PolymerElement) { + + ... + } + customElements.define('x-class', XClass); + + +# LitElement +## A simple base class for creating custom elements rendered with lit-html. + +LitElement uses lit-html to render into the element's Shadow DOM and Polymer's PropertiesMixin +to help manage element properties and attributes. LitElement reacts to changes in properties +and renders declaratively using `lit-html`. + + * **React to changes:** LitElement reacts to changes in properties and attributes by + asynchronously rendering, ensuring changes are batched. This reduces overhead + and maintains consistent state. + + * **Declarative rendering** LitElement uses `lit-html` to declaratively describe + how an element should render. Then `lit-html` ensures that updates + are fast by creating the static DOM once and smartly updating only the parts of + the DOM that change. Pass a JavaScript string to the `html` tag function, + describing dynamic parts with standard JavaScript template expressions: + + * static elements: ``` html`
Hi
` ``` + * expression: ``` html`
${disabled ? 'Off' : 'On'}
` ``` + * attribute: ``` html`
` ``` + * event handler: ``` html`` ``` + + +## Getting started + + * The easiest way to try out LitElement is to use one of these online tools: + + * Runs in all supported browsers: StackBlitz, Glitch + * Runs in browsers with JavaScript Modules: JSFiddle, JSBin, CodePen. + * You can also copy this HTML file into a local file and run it in any browser that supports JavaScript Modules. + + * When you're ready to use LitElement in a project, install it via npm. To run the project in the browser, a module-compatible toolchain is required. We recommend installing the Polymer CLI and using its development server as follows. + + + 1. Add LitElement to your project: + + ```npm i @polymer/lit-element``` + + 2. Create an element by extending LitElement and calling `customElements.define` with your class (see the examples below). + + 3. Install the Polymer CLI: + + ```npm i -g polymer-cli@next``` + + 4. Run the development server and open a browser pointing to its URL: + + ```polymer serve``` + + > LitElement is published on [npm](https://www.npmjs.com/package/@polymer/lit-element) using JavaScript Modules. + This means it can take advantage of the standard native JavaScript module loader available in all current major browsers. + > + > However, since LitElement uses npm convention to reference dependencies by name, a light transform to rewrite specifiers to URLs is required to get it to run in the browser. The polymer-cli's development server `polymer serve` automatically handles this transform. + + Tools like [WebPack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/) can also be used to serve and/or bundle LitElement. + + + +## Minimal Example + + 1. Create a class that extends `LitElement`. + 2. Implement a static `properties` getter that returns the element's properties + (which automatically become observed attributes). + 3. Then implement a `_render(props)` method and use the element's +current properties (props) to return a `lit-html` template result to render +into the element. This is the only method that must be implemented by subclasses. + +```html + + + + +``` + + + diff --git a/Dart.md b/Dart.md new file mode 100644 index 0000000..6d49997 --- /dev/null +++ b/Dart.md @@ -0,0 +1,353 @@ +## Dart + - Dart is the language behind flutter + - Dart is an object oriented language + - can run on Android,ios,desktop and web + +### Variable Delecartion and Initialization + - store values and reference them multiple times + - Variable name should start with small letter. + - Variable name should be declared in camelCase. + - Combination of lowercase and uppercase letter, as well as all digits from 0 to 9 and the underscore character like this + - first character cannot be a digit + +### String Concatenation and Interpolation + To concatenate two string use "+" sign . + Can also use "$" sign inside the string. + e.g print("My name is $firstName $lastname") + + Interpolation can evaluate an expression inside a string with the ${} syntax. + e.g print('Sum is ${num1 + num2}) + +### String Escaping + Write the backslash before the single quote inside the string. + e.g print('Today I\'m feel good') + + Can solve with double quote too. + e.g print("Today I'm feel good") + + You can make a "raw" string by prefixing it with r + e.g print(r'C:\Window\System 32') + +### Multiline String + Use a triple quote (''' or """), with either single quote or double quote at the beginning and at the end. + + e.g print( ''' + the initial newline is ignored + but the last newline is not ignored + '''); + +### Ternary Operator + The conditional operator is considered as short hand for if-else statement. Conditional operator is also called as “Ternary Operator”. + + result = testCondition ? trueValue : falseValue + +### Type inference with "var" + We don't need to declare variable type explicitly,can use "var" instead. + Can be set more than once. + +### The final keyword + The final keyword is used to hardcode the values of the variable and it cannot be altered in future, neither any kind of operations performed on these variables can alter its value (state). + -final means read only (can only be set once) + -If we try to reassign the same variable then it will display error. + + e.g void main() { + final geek1 = "Geeks For Geeks"; + print(geek1); + + // Can't reassign like this + geek1 = "Geeks For Geeks Again!!"; / + + // Assigning value to geek2 + // variable with datatype + final String geek2 = "Geeks For Geeks Again!!"; + + // Printing variable geek2 + print(geek2); + } + +### The Const Keyword + The const keyword in Dart behaves exactly like the final keyword. The only difference between final and const is that the const makes the variable constant from compile-time only. Using const on an object, makes the object’s entire deep state strictly fixed at compile-time and that the object with this state will be considered frozen and completely immutable. + +### Using var,final,const with lists + -You can declare list variables as var,final,const. + -Final and Const variables can only be set once. + -Final variables can't be re-assigned but you can still modify their contents. + -But not with const variable. + +### Sets and List + -Sets are collection of unique values using curly brackets. + -Lists can contain duplicate values using square brackets. + -Sets can use union method, intersection and difference method. + +### Map + -Used to store a collection of key value pairs. + -When declaring a Map with var/final/const, key and values can have any type we want. + -You can add type annotations to lists, sets and maps literals.Type annotations are not required but they help you wirte safer code. + e.g Map person ={ + 'name' : 'Lilly', + 'age' : 20, + }; + +### As Operator + If you declare a map with dynamic values and want to assign map values to variables of specific type,you can use the 'as' operator. + e.g Map person ={ + 'name' : 'Lilly', + 'age' : 20, + }; + var name = person ['name'] as String; + print(name); + + +### Spreads + "..." adds the elements of a list to the enclosing list/collection. + e.g final colors =[ + 'green','gret', + ...['black','cyan'], + ]; + +### The assertion operator(!) + -assign nullable value to non-nullable value. + -IF we're sure that a nullable variable will always have a non-nullable value,we can use the assertion operator(!). + -'!' is also called the bang operator. + e.g void main(){ + int x = 7; + + //To indicate that a variable might have the value null, just add ? + int ? maybeValue; + + if (x > 0){ + maybeValue =x; + } + // valid, value is non-nullable + int value = maybeValue !; + print(value); + } + +### Functions + -encapsulate some code and reuse it multiple times + eg: + void main(){ + sayHi(); + } + + void sayHi(){ + print('Hi'); + print('Welcome'); + } + +### Required and default values + 1.Without null safety : arguments can be omitted. + 2.With null safety: + -make arguments nullable (e.g {String ? name}) + -make arguments non-nullable + use a default value ( e.g {String name = 'Andera'}) + mark them as required ( e.g {required String name}) + 3.Null safety gives you compile-time guarantees about what can and cannot be null. + +### Fat arrow notation(=>) + Need a function body with only one statement?Use the "=>" notation. + + eg: int sum (int x,int y)=>x + y; + +### The where and firstWhere methods + where :filter items inside a collection + firstWhere :find an item inside a collection + eg: + void main(){ + cost list =[1,2,3,4]; + final even =list.where((value)=>value % 2 == 0); + final value =list.firstWhere((x)=>x == 4,orElse:()=> -1); + } + +### The reduce method + -Used to combine all items inside a list and produce a single result. + eg: + void main(){ + cost list =[1,2,3,4]; + final sum =list.reduce((previousValue,element)=>previousValue + element); + } + +### Const constructors + Have a class where all variables are final?User a 'const' constructor. + eg: + class Complex{ + const Complex(this.re,this.im); + final double re; + final double im; + } + +### Static methods and variables + -The static variables belong to the class instead of a specific instance. A static variable is common to all instances of a class: this means only a single copy of the static variable is shared among all the instances of a class. The memory allocation for static variables happens only once in the class area at the time of class loading. + -Use static const to define a global constant that belonds to a class. + -Static variables can be declared using the static keyword followed by data type then the variable name + e.g static [date_type] [variable_name]; + + -The static variable can be accessed directly from the class name itself rather than creating an instance of it. + e.g Classname.staticVariable; + + +### Private variables and methods + -Encapsulate things that should not be accessible outside a class. + -You cannot directly access a private name from a different library + -Private identifier in Dart start with an underscore. ( e.g _balance, _ 123) + +### Abstract classes + -connot be instantiated + -to define an interface that can be implemented by subclasses + -You can always assign an instance of a subclass to a variable of the parent class + eg: + abstract class Shape{ + double get area; + } + + class Square extends Shape{ + Square(this.side); + final double side; + + @override + double get area=>side * side; + } + + void main(){ + // final shape =Shape(); + final square =Square(10); + } + +### Difference between implements and extends + keyword type abstract methods concrete method + + -extends single must override can override + + -implements multiple must override must override + +### Copying objects with copyWith + If yout need copy-behaviour in your immutable classes,create a 'copyWith' method. + eg: + class Credentials { + final String email; + final String password; + + const Credentials({this.email = '', this.password = ''}); + + Credentials copyWith({ + String? email, + String? password, + }) { + return Credentials( + email: email ?? this.email, + password: password ?? this.password, + ); + } + + @override + String toString() => 'Credentials($email,$password)'; + } + + void main() { + const credentials = Credentials(); + final update = credentials.copyWith(email: "example@gamil.com"); + print(update); + } + +### Mixins + -to share functionality in multiple classes without code duplication + -Mixins can't be instantiated + eg: + + mixin Swimming { + void swim() => print('swimming'); + } + + class Animal { + void breathe() => print('breathing'); + } + + class Fish extends Animal with Swimming {} + + class Human extends Animal with Swimming {} + + void main() { + final fish = Fish(); + fish.swim(); + final human = Human(); + human.swim(); + } + +### Extensions + -add functionality to existing classes,without modifying them. + -only named extensions can be imported + eg: + extensins.dart + import number_parsing.dart; + void main(){ + int.tryParse('123'); + '123'.toIntOrNull(); + '456'.toIntOrNull(); + } + + number_parsing.dart + extension numberParsing on String{ + int? toIntOrNull()=>int.tryParse(this); + } +### Asynchronous + Asynchronous operation let your program complete work while waiting for another operation to finish. + -Fetching data from network + -Writing to a database + -Reading data from file + +### Future + - A future represents the result of an asynchronous operation, and can have two states: uncompleted or completed. + -A future can't listen to a variable change. + -It's a one-time response. + +### Async and await + Async + - You can use the async keyword before a function’s body to mark it as asynchronous. + + Await + -You can use the await keyword to get the completed result of an asynchronous expression. The await keyword only works within an async function. + -Await is only allowed inside async functions + -To wait until a future completes + + Future createOrderMessage() async { + var order = await fetchUserOrder(); + return 'Your order is: $order'; + } + + Future fetchUserOrder() => + // Imagine that this function is + // more complex and slow. + Future.delayed( + Duration(seconds: 2), + () => 'Large Latte', + ); + + Future main() async { + print('Fetching user order...'); + print(await createOrderMessage()); + } + +### Stream + -Streams provide an asynchronous sequence of data. + -There are two kinds of streams: single subscription or broadcast. + + Future sumStream(Stream stream) async { + var sum = 0; + await for (var value in stream) { + sum += value; + } + return sum; + } + + Stream countStream(int to) async* { + for (int i = 1; i <= to; i++) { + yield i; + } + } + + Future main() async { + var stream = countStream(10); + var sum = await sumStream(stream); + print(sum); // 55 + } + \ No newline at end of file diff --git a/DataSystem.md b/DataSystem.md new file mode 100755 index 0000000..83f7c42 --- /dev/null +++ b/DataSystem.md @@ -0,0 +1,873 @@ +# Data system concepts + + 1. Observers- Callbacks invoked when data changes. + + 2. Computed properties- Virtual properties computed based on other properties, and recomputed when the input data changes. + + 3. Data bindings- Annotations that update the properties, attributes, or text content of a DOM node when data changes. + +Simple element: + + class NameCard extends PolymerElement { + constructor() { + super(); + this.name = {first: 'Kai', last: 'Li'}; + } + static get template() { + return html ` +
[[name.first]] [[name.last]]
+ `; + } + } + customElements.define('name-card', NameCard); + + + 1. The `` element has a name property that refers to a JavaScript object. + + + 2. The `` element hosts a local DOM tree, that contains a single
element. + + + 3. Data bindings in the template link the JavaScript object to the
element. + + + For example, + + the `` element has data bindings for the paths "name.first" and "name.last" + + + ## Observable changes +-Setting a direct property of the element. + + this.owner = 'Jane'; + +-Setting a subproperty of the element using a two way data binding. + + + + ## Unobservable changes + + -Setting a subproperty of an object. + + // unobservable subproperty change + this.address.street = 'Elm Street'; + +-Mutating an array: + + // unobservable change using native Array.push + this.users.push({ name: 'Maturin'}); + +## Mutating objects and arrays observably +Polymer provides methods for making observable changes to subproperties and arrays: + + // mutate an object observably + this.set('address.street', 'Half Moon Street'); + + // mutate an array observably + this.push('users', { name: 'Maturin'}); + +#### Batched property changes + +You can atomically set multiple properties using the setProperties method. + + this.setProperties({item: 'Orange', count: 12 }); + +For example, + + // observer fires twice + this.a = 10; + this.b = 20; + + // observer fires once + this.setProperties({a: 10, b: 20}); +The two types of data binding annotations are: + + +### 1 - Automatic, + which allows upward (target to host) and downwards (host to target) data flow. Automatic bindings use double curly brackets ({{ }}): + + +### 2 - One-way, + which only allows downwards data flow. Upward data flow is disabled. One-way bindings use double square brackets ([[ ]]). + + + +#### Example of one-way binding (downward) + + class XHost extends PolymerElement { + static get template() { + return html` + + `; + } + } +.................... + + ... + class XTarget extends PolymerElement { + static get properties() { + return { + someProp: { + type: String //no notify: true + } + } + } + } + ... + + ... + class XHost extends PolymerElement { + static get template() { + return html` + + + + `; + } + } + ... + +#### Example of one-way binding (upward, child-to-host) + + + ... + class XTarget extends PolymerElement { + static get properties() { + return { + someProp: { + type: String, + notify: true, + readOnly: true + } + } + } + } + ... + customElements.define('x-target', XTarget); +... + + class XHost extends PolymerElement { + static get template() { + return html` + + + + `; + } + } + ... + customElements.define('x-host', XHost); + +#### Example of no data flow / nonsensical state + + ... + class XTarget extends PolymerElement { + static get properties() { + return { + someProp: { + type: String, + notify: true, + readOnly: true + } + } + } + } + ... + customElements.define('x-target', XTarget); +... + + class XHost extends PolymerElement { + static get template() { + return html` + + + + `; + } + } + ... + customElements.define('x-host', XHost); + + +## Property effects + + 1. Computed properties. + 2. Data bindings. + 3. Reflected values. + 4. Observers. + 5. Change notification events. + + + #### Data bindings + + Two-way property binding: + + target-property="{{hostProperty}}" + +One-way property binding: + + target-property="[[hostProperty]]" + +Attribute binding: + + target-attribute$="[[hostProperty]]" + +# Work with object and array data + +Get a value by path +Use the get method to retrieve a value based on its path. + +// retrieve a subproperty by path + + var value = this.get('myProp.subProp'); +// Retrieve the 11th item in myArray + + var item = this.get(['myArray', 11]) + +### Set a property or subproperty by path + Use the set method to make an observable change to a subproperty. + + // clear an array + this.set('group.members', []); + + // set a subproperty + this.set('profile.name', 'Alex'); + + ### Working with arrays +Example + + import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; + import '@polymer/polymer/lib/elements/dom-repeat.js'; + + class XCustom extends PolymerElement { + static get template() { + return html` + +

+ `; + } + constructor() { + super(); + this._reset(); + } + addUser() { + var user = "wing sang"; + this.push('users', user); + } + removeUser() { + var user = "wing sang"; + var index = this.users.indexOf(user); + this.splice('users', index, 1); + } + _reset() { + this.users=["wing sang", "deshaun", "kelley"]; + } + } + customElements.define('x-custom', XCustom); + +### Batch multiple property changes + +Use **setProperties** method to make a batch change to a set of properties. This ensures the property changes run as a coherent set. + + this.setProperties({ + date: 'Jan 17, 2017', + verified: true + }); + +**setProperties** supports an optional **setReadOnly** flag as the second parameter. If you need to set read-only properties as part of a batch change, pass true for the second parameter: + + this.setProperties({ + date: 'Jan 17, 2017', + verified: true + }, true); + +#### Link two paths to the same object + + linkPaths('selectedUser', 'users.1'); + + +To remove a path linkage, call **unlinkPaths**, passing in the first path you passed to linkPaths: + + unlinkPaths('selectedUser'); + + +# Observers and computed properties +- Simple observers observe a single property. +- Complex observers can observe one or more properties or paths. + +## Simple observers +Simple observers are declared in the properties object, and always observe a single property. +Simple observers only fire when the property itself changes. They don't fire on subproperty changes, or array mutation. If you need these changes, use a complex observer with a wildcard path + +### Observe a property +Define a simple observer by adding an observer key to the property's declaration, identifying the observer method by name. + +Example + + import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + + class XCustom extends PolymerElement { + static get properties() { + return { + active: { + type: Boolean, + // Observer method identified by name + observer: '_activeChanged' + } + } + } + // Observer method defined as a class method + _activeChanged(newValue, oldValue) { + this.toggleClass('highlight', newValue); + } + } + customElements.define('x-custom', XCustom); + + +The observer method is usually defined on the class itself, although an observer method can also be defined by a superclass, subclass, or a class mixin, as long as the named method exists on the element. + +## Complex observers +Complex observers are declared in the observers array. Complex observers can monitor one or more paths. These paths are called the observer's dependencies. + + static get observers() { + return [ + // Observer method name, followed by a list of dependencies, in parenthesis + 'userListChanged(users.*, filter)' + ] + } + +Each dependency represents: + + - A specific property (for example, firstName). + + - A specific subproperty (for example, address.street). + + - Mutations on a specific array (for example, users.splices). + + - All subproperty changes and array mutations below a given path (for example, users.*). + +### Observe changes to multiple properties + +To observe changes to a set of properties, use the observers array. + +Observers do not receive old values as arguments, only new values. Only single-property observers defined in the properties object receive both old and new values. + + +Example + + import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + + class XCustom extends PolymerElement { + + static get properties() { + return { + preload: Boolean, + src: String, + size: String + } + } + + // Each item of observers array is a method name followed by + // a comma-separated list of one or more dependencies. + static get observers() { + return [ + 'updateImage(preload, src, size)' + ] + } + + // Each method referenced in observers must be defined in + // element prototype. The arguments to the method are new value + // of each dependency, and may be undefined. + updateImage(preload, src, size) { + // ... do work using dependent values + } + } + + customElements.define('x-custom', XCustom); + + +## Observe sub-property changes + +- Define an observers array. +- Add an item to the observers array. The item must be a method name followed by a comma-separated list of one or more paths. For example, **onNameChange(dog.name) for one path, or onNameChange(dog.name, cat.name) for multiple paths**. **Each path is a sub-property** that you want to observe. +- Define the method in your element prototype. When the method is called, the argument to the method is the new value of the sub-property. + + +Example + + import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; + + class XCustom extends PolymerElement { + static get template () { + return html` + + + `; + } + static get properties() { + return { + user: { + type: Object, + value: function() { + return {}; + } + } + } + } + // Observe the name sub-property on the user object + static get observers() { + return [ + 'userNameChanged(user.name)' + ] + } + // For a property or sub-property dependency, the corresponding + // argument is the new value of the property or sub-property + userNameChanged: function(name) { + if (name) { + console.log('new name: ' + name); + } else { + console.log('user name is undefined'); + } + } + } + customElements.define('x-custom', XCustom); + +## Observe array mutations + + static get observers() { + return [ + 'usersAddedOrRemoved(users.splices)' + ] + } + +- indexSplices. The set of changes that occurred to the array, in terms of array indexes. Each indexSplices record contains the following properties: + - index. Position where the splice started. + - removed. Array of removed items. + - addedCount. Number of new items inserted at index. + - object: A reference to the array in question. + - type: The string literal 'splice'. + + + +Example + + import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + + class XCustom extends PolymerElement { + static get properties() { + return { + users: { + type: Array, + value: function() { + return []; + } + } + } + } + // Observe changes to the users array + static get observers() { + return [ + 'usersAddedOrRemoved(users.splices)' + ]; + } + // For an array mutation dependency, the corresponding argument is a change record + usersAddedOrRemoved(changeRecord) { + if (changeRecord) { + changeRecord.indexSplices.forEach(function(s) { + s.removed.forEach(function(user) { + console.log(user.name + ' was removed'); + }); + for (var i=0; i + + `; + } + static get properties() { + return { + user: { + type: Object, + value: function() { + return {'name':{}}; + } + } + } + } + static get observers() { + return [ + 'userNameChanged(user.name.*)' + ] + } + userNameChanged(changeRecord) { + console.log('path: ' + changeRecord.path); + console.log('value: ' + changeRecord.value); + } + } + customElements.define('x-custom', XCustom); + + static get properties() { + return { + firstName: { + type: String + }, + lastName: { + type: String + } + } + } + + static get observers() { + return [ + 'nameChanged(firstName, lastName)' + ] + } + + nameChanged: function(firstName, lastName) { + console.log('new name:', firstName, lastName); + } + +## Computed properties + +Note: The definition of a computing function looks like **the definition of a multi-property observer**, and the two act almost identically. The only difference is that the computed property function returns a value that's exposed as a virtual property. + + import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; + + class XCustom extends PolymerElement { + static get template() { + return html` +

My name is {{fullName}}

+ `; + } + static get properties() { + return { + first: String, + last: String, + fullName: { + type: String, + // when `first` or `last` changes `computeFullName` is called once + // and the value it returns is stored as `fullName` + computed: 'computeFullName(first, last)' + } + } + } + computeFullName(first, last) { + return first + ' ' + last; + } + } + customElements.define('x-custom', XCustom); + +## Dynamic observer methods +For example, + + import { PolymerElement } from '@polymer/polymer/polymer-element.js'; + + class NameCard extends PolymerElement { + static get properties() { + return { + // Override default format by assigning a new formatter + // function + formatter: { + type: Function + }, + formattedName: { + computed: 'formatter(name.title, name.first, name.last)' + }, + name: { + type: Object, + value() { + return { title: "", first: "", last: "" }; + } + } + } + } + constructor() { + super(); + this.formatter = this.defaultFormatter; + } + defaultFormatter(title, first, last) { + return `${title} ${first} ${last}` + } + } + customElements.define('name-card', NameCard); + +Setting a new value for formatter causes the formattedName property to update, even if the name property doesn't change: + + nameCard.name = { title: 'Admiral', first: 'Grace', last: 'Hopper'} + console.log(nameCard.formattedName); // Admiral Grace Hopper + nameCard.formatter = function(title, first, last) { + return `${last}, ${first}` + } + console.log(nameCard.formattedName); // Hopper, Grace + + +### Add a simple observer dynamically +You can create a simple observer dynamically using the _createPropertyObserver instance method. For example: + + this._observedPropertyChanged = (newVal) => { console.log('observedProperty changed to ' + newVal); }; + this._createPropertyObserver('observedProperty', '_observedPropertyChanged', true); + +### Add a complex observer dynamically +You can create a computed property dynamically using the _createMethodObserver instance method. For example: + + this._createMethodObserver('_observeSeveralProperties(prop1,prop2,prop3)', true); + +### Add a computed property dynamically +You can create a computed property dynamically using the _createComputedProperty instance method. For example: + + this._createComputedProperty('newProperty', '_computeNewProperty(prop1,prop2)', true); + + +# Data Bindings + +A data binding connects data from a custom element (the host element) to a property or attribute of an element in its local DOM (the child or target element). + + static get template() { + return html` + + `; + } + +### Bind to a target property + + + +This example binds the target element's name property to the host element's myName property. + + +### Bind to text content + To bind to a target element's textContent, you can simply include the annotation or compound binding inside the target element. + + import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; + + class UserView extends PolymerElement { + static get properties() { + return { + name: String + }; + } + static get template() { + return html` +
[[name]]
+ `; + } + } + customElements.define('user-view', UserView); + + + +### Bind to a target attribute + +To bind to an attribute, add a dollar sign ($) after the attribute name: + +
+ +Attribute binding results in a call to: + + element.setAttribute(attr,value); + +As opposed to: + + element.property = value; + +For example: + + static get template() { + return html` + + + + + + + + `; + } + +### Bind to a host sub-property + +main-view.js + + import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; + import './user-view.js'; + + class MainView extends PolymerElement { + static get properties() { + return { + user: { + type: Object, + value: function () { return { given: "San", family: "Zhang" }; } + } + }; + } + static get template() { + return html` + + `; + } + } + customElements.define('main-view', MainView); + +user-view.js + + import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; + + class UserView extends PolymerElement { + static get properties() { + return { + given: String, + family: String + }; + } + static get template() { + return html` +
[[given]] [[family]]
+ `; + } + } + customElements.define('user-view', UserView); + +index.html + + + +## Logical not operator + + static get template() { + return html` + + `; + } + +### Computed bindings + +
[[_formatName(first, last, title)]]
+ +A computed binding is useful if you don't need to expose a computed property as part of the element's API, or use it elsewhere in the element. Computed bindings are also useful for filtering or transforming values for display. + +Example + + class XCustom extends PolymerElement { + static get properties() { + return { + given: String, + family: String + }; + } + + _formatName(given, family) { + return `${family}, ${given}`; + } + + static get template() { + return html` + My name is [[_formatName(given, family)]] + `; + } + } + customElements.define('x-custom', XCustom); + +### Literal arguments to computed bindings + + +Example: + + static get template() { + return html` + {{translate('Hello\!\, nice to meet you', given, family)}} + `; + } + +### Compound bindings +You can combine string literals and bindings in a single property binding or text content binding. For example: + + + + Name: [[lastname]], [[firstname]] + + +## Binding to arrays and array items + + + {{array[0]}} + + {{array.0}} + +### Bind to an array item +You can use a computed binding to bind to a specific array item, or to a subproperty of an array item, like array[index].name. + + + class XCustom extends PolymerElement { + static get properties() { + return { + myArray: { + type: Array, + value: [{ name: 'Bob' }, { name: 'Wing Sang' }] + } + }; + } + // first argument is the change record for the array change, + // change.base is the array specified in the binding + arrayItem(change, index, path) { + // this.get(path, root) returns a value for a path + // relative to a root object. + return this.get(path, change.base[index]); + } + ready() { + super.ready(); + // mutate the array + this.unshift('myArray', { name: 'Fatma' }); + // change a subproperty + this.set('myArray.1.name', 'Rupert'); + } + static get template() { + return html` +
[[arrayItem(myArray.*, 0, 'name')]]
+
[[arrayItem(myArray.*, 1, 'name')]]
+ `; + } + } + + +## Two-way binding to a non-Polymer element + +Example + + + + + + + + +