The method mentioned in this answer: https://stackoverflow.com/a/19818178/194642 does not seem to work anymore. How does one use web component's element in angular.dart component?
#Component(
selector: "custom-elem",
template: "<div id='container-elem'> <content></content></div>")
class CustomElem extends ShadowRootAware{
onShadowRoot(_) {
//do something
}
}
Now, I would expect the following html fragment:
<custom-elem>
<span>Sample content</span>
</custom-elem>
to result in following within #shadow-root:
<div id='container-elem'>
<content>
<span>Sample content</span>
</content>
</div>
I'm not sure if I understand your question or your expected result correctly but the <content> tag works the way that <span>Sample content</span> are children of <custom-elem> where <div id='container-elem'> is put in the Shadow DOM of <custom-elem> before the children and </div> in the Shadow DOM of <custom-elem> after the children but the <span> is in the light DOM like it would be when used like
<div>
<span>Sample content</span>
</div>
When you inspect the Shadow DOM of <custom-elem> there should just be the template part of your Angular component.
Related
I am trying to use jquery datepicker in my project, but I want to show it when the user in editing mode. When I use it without if statement, it works perfect, but when I put in if statement, it does not render. How can I solve this?
This is the part of my template
{{#if editing_duedate}}
<input class="datepicker" name="date">
{{else}}
<div class="row text-center">
<div class="eventduedate">
{{duedate}}
</div>
</div>
{{/if}}
This where I render datepicker
Template.assignmenttodositem.rendered = function() {
$('.datepicker').datepicker();
};
This is my template events
Template.assignmenttodositem.events({
......
'dblclick .eventduedate':function(evt,tmpl){
evt.preventDefault();
Session.set('editingduedate', this._id);
}
..........
This is where I check if statement
Template.assignmenttodositem.editing_duedate = function () {
return Session.equals('editingduedate', this._id);
};
Rendered is executed only once, when template is rendered.
In that time else part is not put to HTML so .datepicker cannot be found.
You need to check whether editinduedate variable is updated and then create datePicker component.
Template.assignmenttodositem.rendered = function() {
var self = this;
this.autorun(function(){
if(Session.equals("editingduedate", self.data._id )){
$('.datepicker').datepicker();
}
})
};
HTML
<template name="assignmenttodositem">
{{#if editing_duedate}}
{{> datepicker}}
{{else}}
...
{{/if}}
</template>
<template name="datepicker">
<input class="datepicker" name="date">
</template>
JS
Template.datepicker.rendered=function(){
this.$('.datepicker').datepicker();
};
The rendered callback is executed only once when your template instance is inserted in the DOM : triggering the datepicker initialization in the enclosing template containing the #if statement is not going to work because when it is executed, we are in the else state so the input is not there yet.
To solve this problem simply, just move the datepicker in its own template (this has always been considered a good design pattern in programming anyway, whenever you can, decompose your main task in smaller easier solvable tasks), this way its rendered callback will get executed at appropriate time.
Put the datepicker in it's own template. Then initialize the datepicker in template.datepicker.rendered . If you forget the 'this' context, it will not work. Make sure your template.datepicker.rendered includes the following
this.$('#datepicker').datepicker();
where #datepiker refers to id='datepicker' of the datepicker in html.
Let's say I have a component:
#Component(selector: 'app-menu',
templateUrl: '.../menu.html',
cssUrl: const ['.../menu.css'],
publishAs: 'Menu')
class MenuComponent {
bool showOptions = true;
void toggleOptions() {
showOptions = !showOptions;
}
}
And a view for the component:
<div class="menu" ng-click="Menu.toggleOptions()">
<span icon="drawer"></span>
<ul ng-show="Menu.showOptions" class="options">
<!-- I want put content here -->
</ul>
</div>
Finally, the usage (theoretically):
<app-menu>
<menu-item>Remove</menu-item>
</app-menu>
After running the program I'd like to see <menu-item>Remove</menu-item> inside shadow root where I've put <!-- I want put content here -->. I've read that there were a <content /> component but it isn't working like that (nothing happened, I've seen only <output/> element). Also I've tried ng-transclude directive with no success.
Can someone help me and point the right way to do this?
Well,
After some tests and looking into Angular Dart tutorials I've found a solution.
My example above isn't actually accurate. I've used an <li> element instead of <menu-item>. Somehow, when I changed "li" to "span" it just started working. Perhaps DOM parser have rejected "li" element before it has been attached into correct structure inside shadow root tree. I don't really know.
However right after the change it started working.
I am trying to bind jquery mobile horizantal radio buttons using knock out teplate binding.
The fielsset in template looks like
<fieldset data-role="controlgroup" data-bind="attr: {id:QuestionID+'_fld'},template: {name:'optionTemplate', foreach: OptionList}">
</fieldset>
and the option template looks like
<script type="text/x-jquery-tmpl" id="optionTemplate">
<input type="radio" data-bind="attr: { id:OptionID+'_radio',value:OptionID, name: QuestionID+'_rd'}, checked:$parent.OptionId" />
<label data-bind="text:OptionText, attr: {id:OptionID+'_optn', for : QuestionID+'_rd' }"> </lable>
</script>
I have tried
$('input[type=radio]').checkboxradio().trigger('create');
$('fieldset').controlgroup().trigger('create');
Here my problem is that the mobile css is not applying to the fiedset.
You must do this after the template has built your page or during the page initialization event, something like this:
$(document).on('pagebeforeshow', '#pageID', function(){
});
Page content can be enhanced ONLY when content is safely loaded into the DOM.
Second this do NOT mix refresh functions with trigger create. Either one or the other. Trigger create is used to enhance whole content, and it should NOT be used on single elements. No point in restyling whole page every time you add new content.
Basically you only want to use:
$('input[type=radio]').checkboxradio().checkboxradio('refresh');
or if first line throws an error:
$('input[type=radio]').checkboxradio();
and:
$('fieldset').controlgroup();
But I would advise you to only use this line after everything has been appended:
$('#contentID').trigger('create');
where #contentID is an id of your div data-role="content" object. Or in case you are not using content div, only data-role="page" div then use this:
$('#pageID').trigger('pagecreate');
where #pageID is an id of your page.
To find out more about marku enhancement of dynamically added content take a look at this answer.
I'm working on my first Dart app, having completed the Game of Darts tutorials. I am trying to create a semantically named top-menu element that will eventually display a list of navigation menu tabs at the top of my page. My Dart app is able to recognize my custom element and calls the associated constructor.
However, I am getting a null reference when trying to query for the UL element within my custom element. I need the UL reference in order to dynamically load my LI elements into the menu.
Question 1:
Should the element be visible in the DOM at the point where the constructor is running?
Question 2:
If it is not yet visible, is there a Dart event I can use to trigger loading of the LI elements after the custom element has been completely loaded into the DOM?
Thanks in advance! For reference, here is the source of my custom element:
topmenu-element.html
<!DOCTYPE html>
<html>
<body>
<element name="top-menu" constructor="TopMenu" extends="div">
<template>
<div>
Top Menu
<ul id="top-menu-list"></ul>
</div>
</template>
<script type="application/dart" src="topmenu-element.dart"></script>
</element>
</body>
</html>
topmenu-element.dart
import 'package:web_ui/web_ui.dart';
import 'dart:html';
class TopMenu extends WebComponent {
List menuItems = ['Session', 'Authentication Services', 'Vehicle Services', 'Subscriber Services', 'Data Services'];
void populateMenu() {
UListElement menuList = query('#top-menu-list');
LIElement newMenuItem = new LIElement();
newMenuItem.text = menuItems[0];
menuList.children.add(newMenuItem);
}
TopMenu() {
// populateMenu();
}
}
I can't speak specifically about the DOM visibility in a constructor with the query method as I'm truthfully not certain. However there are perhaps better methods which you can use, which are called at various stages in the elements lifecycle.
That said, can I ask why you need to use this particular method to add the children. It is probably much easier to do it with the template repeat like so:
<!DOCTYPE html>
<html>
<body>
<element name="top-menu" constructor="TopMenu" extends="div">
<template>
<div>
Top Menu
<ul id="top-menu-list">
<li template repeat="item in menuItems">{{item}}</li>
</ul>
</div>
</template>
<script type="application/dart" src="topmenu-element.dart"></script>
</element>
</body>
</html>
Then there's no need to put any of your menu display code in your constructor.
Can someone tell me why this works:
<div data-bind="with: selectedItem">
<div id="dialog" data-bind="jqDialog: {title: drugName}">
//contents of a jquery ui modal
</div>
</div>
But trying to do the same with KO virtual elements does not work:
<!-- ko with: selectedItem -->
<div id="dialog" data-bind="jqDialog: {title: drugName}">
//contents of a jquery ui modal
</div>
<!-- /ko -->
I get the following error:
Error: Unable to parse bindings.
Message: ReferenceError: drugName is not defined;
Bindings value: jqDialog: {title: drugName}
I'd like to get rid of that div wrapper which just holds the data-bind attribute. I figured the virtual elements would make this a breeze.
Edit: Here's kind of the core to the page (though it won't run in the fiddle), http://jsfiddle.net/B8g5J/
I'm not sure if you have sorted this out, but is it possible that your server is configured to remove comments?
See: Knockout.js Virtual Elements Work Locally But Not Remotely