If I have a custom element
Polymer({
name: 'dane',
computed: {
message: 'greet(name)'
},
greet: function(name) {
return 'hello ' + name + Date.now();
}
})
When I change name polymer will automatically recompute message, but is there a way to recompute message without changing name?
You could add another input value to the compute expression, i.e.:
message: 'greet(name,x)'
and then force a re-compute by updating x.
Keep in mind computed properties are read-only so you can't directly assign it a value.
Related
I have a variable defined like this (not sure if it should be with let or var in the first place):
let activated = false;
The first thing that the extension should do is check the value of activated. I think this is the correct syntax:
chrome.storage.local.get(['activated'], function(result) {
activated = result.activated
alert ("activated: " + result.activated)
});
After some logic, I want to change activetedto true, with this syntax:
chrome.storage.local.set({activated: true}, function() {
console.log("activated changed to true: " + activated)
});
However, when I close and open the browser again, activatedis set to false again.
How should I structure this in order to achieve the desired result?
The way to acess a localstorage variable isn't by defining as I was doing in let activated = false;.
The way to add the variable retrieved from localstorage to the program's control flow should be done this way:
chrome.storage.local.get(['activated'], function(result) {
if (result.activated == value) { // Do something }
});
I need to manipulate values from a raw API data for display to the user and manipulate them again before sending the update through the API. I'm using core-input for each value, but I'm having difficulty setting the initial value and binding to the correct update event.
<input id="host" is="core-input">
My first problem is that I don't know how to set and manipulate the initial value without also binding to the live changes stream. I tried binding only to committedValue but it does not set the initial value for the field.
However, even when I set commitedValue, I am unable to trigger it. I enter text into the field and then switch fields or press the enter key and nothing happens.
<input id="host" commitedValue="{{record | setHost}}" is="core-input">
And the JavaScript:
setHost: {
toDOM: function(record) {
if(record.host === "#"){
return record.domain;
} else {
return record.host + "." + record.domain;
}
},
toModel: function(value) {
if(record.host === "#"){
return record.domain;
} else {
return record.host + "." + record.domain;
}
}
}
To set the initial value, I think you can do a one-time binding.
<template is="auto-binding">
<input is="core-input" type="text" value="[[foo]]">
</template>
<script>
var tmpl = document.querySelector('template');
tmpl.foo = 'bar';
</script>
It seems like the approach you're trying to take with commitedValue may not be supported, because you can't actually write to commitedValue.
From the core-input docs on commitedValue
Setting this property has no effect on the input value.
It might be better to listen to on-change or on-blur (or both), handle the change, and then manually update value
Instead of:
Polymer({
observe: {
'key1': 'onDataChange',
'key2': 'onDataChange'
},
Can one programmatically execute an observer function for any data attribute data change (top-level)? I tried setting this.observe after creating an observe block object by looping over this.attributes, but that didn't work.
I don't think that there's support for "wildcards" in the keys of the observe block, but you can specify a space-separated list of attributes that share the same data-changed observer function.
E.g.
observe: {
'key1 key2': 'onDataChange'
}
You can see a real world example of it in the <google-youtube-video-wall> element.
(I'm not exactly sure why it's not documented, though. I'll follow up on that.)
An alternative to using an observe block is to add a callback for the attributeChanged element lifecycle event, e.g.:
Polymer({
// ...
attributeChanged: function(attrName, oldVal, newVal) {
console.log(attrName, 'old: ' + oldVal, 'new:', newVal);
}
// ...
});
I've been studying AngularJS and in particular saw the video:
http://www.thinkster.io/pick/IgQdYAAt9V/angularjs-directives-talking-to-controllers
This video presents an example of a directive talking to a controller which I've modified a bit to try and understand if one could also use an isolate scope to get a similar result. Consider an HTML snippet such as:
<div enter="loadMoreTweets()">Roll Over This</div>
and an Angular controller and directive defined as:
app.controller('scopeCtrl', function($scope) {
$scope.loadMoreTweets = function () {
alert("loading more tweets");
}
}).directive('enter', function() {
return {
restrict: "A",
scope: {enter: "#"},
link: function(scope, element, attrs) {
element.bind("mouseenter", function() {
//scope.$apply(attrs.enter);
scope.$apply(scope.enter);
})
}
}
});
Rolling over the DIV causes no errors and has no effect.
If I comment out the isolate scope and use the commented line in the element.bind() rather than the reference to scope.enter then rolling over the DIV causes the alert() to display as expected.
Question: If the "#" isolate scope creates a one-way binding between the attribute's value and the scope's property then I would have expected that scope.enter == attrs.enter. Clearly this isn't true. Why?
The reason for that is that '#' is a one way data binding but it's passed always as a string
scope: { // set up directive's isolated scope
name: "#", // name var passed by value (string, one-way)
age: "=", // age var passed by reference (two-way)
showName: "&" // passed as function
}
The at sign "#" indicates this variable is passed by value. The directive receives a string that contains the value passed in from the parent scope. The directive may use it but it cannot change the value in the parent scope (it is isolated).
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