replace component with its content - angular 2 [duplicate] - javascript

This question already has answers here:
Remove the host HTML element selectors created by angular component
(5 answers)
Closed 7 years ago.
I am looking for a way to have a component that is rendered only with its content. For example, Given the component:
#Component({selector: 'my-cmp', template: '<div> my-cmp </div>'})
class MyComponent {
}
rendering it with angular2 will add the following to the DOM:
<my-cmp>
<div> my-cmp </div>
</my-cmp>
While I want to find a way to render it directly as:
<div> my-cmp </div>
Sadly since angular 2 is relatively new (just went beta) - Google is not so helpful, not to mention how lacking the current documentation is..

Sort of the same can be achieved by using an attribute selector
camelCasing is mandatory for attributes since alpha.52
#Component({
selector: '[myCmp]', //attribute selector
template: 'my-cmp'
})
class MyComponent {
}
And use this to call it:
<div myCmp></div>

You can do somethink like the following:
#Component({selector: 'div.my-cmp', template: 'my-cmp'})
class MyComponent {
}
and in your HTML:
<div class="my-cmp" />

According to documentation of angular 1.x
Replace the directive's element itself (if replace is true -
DEPRECATED).
So i think this feature won't be available it angular 2

I remember asking a similar question for Angularjs a few years ago. The concensus seemed to be then, as it is might be now is you probably don't want to do that.
It breaks semantics: a <video/> or a <input/> does not decompose into its contents. Your Angular components should not either.
You can probably still achieve what you want by thinking more deeply about your markup/css? Perhaps if you flesh out your use case we might be able to give you an alternative?

Related

Vue.js workflow from Vue.js 1 to 2

I have followed the Vue.js lessons from laracasts when Vue.js 1 came out and I used to do something like this:
import Comments from './components/Comments.vue';
import Upload from './components/Upload.vue';
new Vue({
el: 'body',
components: {
Comments,
Upload,
Preview,
Algolia,
},
etc,
});
This allowed me to kind of 'sprinkle' components all over my application. I can no longer bind to the body though because Vue replaces the content and also throws an error message saying you shouldn't bind to the body or html.
I followed a couple of lessons for Vue.js 2 but how can I replicate this workflow in the Vue.js 2 manner? I loved just binding to the body and having the option to place a component here and there with the custom tags.
We use the same "sprinkling" approach and all we did was change it from 'body' to '#app'.
We also added a wrapping element inside that had this id to basically replicate body. (https://github.com/onespacemedia/project-template/blob/develop/%7B%7Bcookiecutter.repo_name%7D%7D/%7B%7Bcookiecutter.package_name%7D%7D/templates/base.html#L62)
<body>
<div id="app">
...
</div>
</body>
We use Jinja2 for our templating language and have found when a variable that doesn't resolve in Jinja2 it tanks Vue as well as i think Vue tries to use it.
I believe it takes everything inside #app after initial render and converts it to virtual dom. This doesn't effect anything from what i've seen though so you can happily just add the wrapping class inside body and use it the same as Vue 1

How can I embed angular directive style within the js code?

I have a project written in angular 1.5 Until I upgrade to angular 2, I would like to reach a state where I write something like
angular.module(..).directive('name', () => {
return {
restrict: 'A',
template: `
<div> ... some template... </div>
`,
style: `// this is what I am missing
div{
// some css
}
`,
controller: function($scope){ ... }
}
})
The only piece I am missing is the style part. How can I get that? Is it supported in angular 1.x? Is there a tool that can help me get this functionality?
To make it clear - I am not asking about scoped css.
I don't care that these rules will be global or not.
I just want to be able to write the css next to the template and the controller.
So if you know about a tool like babel for example that can extract the style part to a css/scss file, that would qualify.
It can even be a general solution that I can use for this scenario.
Taken from Reddit
To my knowledge, there is no way to do that "automatically". Personally when i create a component i just give a specific ID / class to the top element, and restrict the component's CSS to that element.
Example: my-component.html
<div class="my-component-wrapper">
....
</div>
my-component.scss
.my-component-wrapper {
// style that applies only to my component
}
A style property on an angular 1.5 component is not supported or it'd have been mentioned in the docs

Directive loaded from ng-bind-html doesn't execute [duplicate]

This question already has answers here:
angular ng-bind-html and directive within it
(6 answers)
Closed 6 years ago.
Inside the controller:
$scope.content = $sce.trustAsHtml('<some-directive></some-directive>');
The template:
<!-- Works perfectly -->
<some-directive></some-directive>
<!-- HTML loaded correctly, but the directive inside won't execute -->
<div class="article__main" ng-bind-html="content"></div>
What is going on here, exactly? How do I tell angular to check the DOM for new directives that are going to be added via ng-bind-html? BTW, I'm testing now and the directive is just logging to console, nothing else.
I used ng-include + a file on another version of the website (instead on ng-bind-html) and that worked.
Thanks on advance :)
You need to use the $compile Service.
var compiledTemplate = $compile(content)(scope);
You also have to define the parent scope.Here is the Doku to $compile
I never used it with ng-bind-html but setting it on the DOM with element.append() works just fine

ARIA attributes in ember core form components

I'd like to use ARIA attributes in Ember core form components, such input and textarea fields.
I noticed that using an aria attribute within the component in my template, it doesn't work at all
{{input aria-label="Your name"}}
{{textarea aria-label="Your address"}}
So I decided to reopen the core components in an initializer to add this attribute to the components
export default {
name: 'reopenTextAreaComponent',
initialize: function () {
Ember.TextArea.reopen({
attributeBindings: ['aria-label']
});
}
};
Since I did that, the performance of my application is pretty bad. The integration tests take much more time than before.
I tried not to use their components and simply a HTML tag:
<textarea {{bind-attr aria-label="Your address"}}>{{value}}</textarea>
But this doesn't compile with handlebars! It returns an error because of the {{value}} within the textarea tag.
What is the solution to avoid reopening? Should I create my own component?
Thanks
From Ember 2.8+, the simplest way of doing this is to install ember-component-attributes, like this:
ember install ember-component-attributes
Then you can add aria-label, other ARIA attributes and whatever other attributes you might require as follows:
{{input (html-attributes aria-label="Your name")}}
{{textarea (html-attributes aria-label="Your address")}}
What is the solution to avoid reopening? Should I create my own component?
Those are your two options.
I think you have the correct approach regarding the reopening of Ember.TextArea, because you want to have aria-label available on all instances.
I use a similar initializer - with one difference being that I reopen Ember.TextSupport so that both Ember.TextField and Ember.TextArea will have the aria-label binding.
// initializers/input.js
import Ember from 'ember';
export function initialize(/* application */) {
Ember.TextSupport.reopen({
attributeBindings: ['aria-label']
});
}
You could try creating your own component(s) to see if there is any difference in performance, but I think reopening is the right approach in this case.

How to observe multiple states in a handlebar template from an ember controller or component

I'm new to ember and am struggeling with the typical "how would one do that"-Problem. What I've got is fairly simple and I know how to do it, but my way is so complicated that I do not think it's correct.
The case:
<ul>
<li>{{link-to top-level}}</li>
<li>{{link-to another-top-level</li>
<ul class="submenu">
<li>{{link-to submenu</li>
</ul>
</ul>
What should happen is:
When a route is clicked, the corresponding list element should become active.
When a submenu is clicked the corresponding upper ul-element should get the class open
It's a fairly simple case with jQuery, but I understand that this is not scalable and abstracted and stuff.
Therefore I started with this approach:
Create a controller / template construct for the entire navigation to handle it's state (there are some other things I need to check as well, so it came in handy).
since ember adds the active class to the anchor tag I created a component to observe that:
Like:
export default Ember.Component.extend({
tagName: 'li',
classNameBindings: ['active'],
active: function() {
return this.get('childViews').anyBy('active');
}.property('childViews.#each.active')
});
Replacing the li elements with {{linked-list}} does indeed work.
But what next? Do I need to add another component to watch the component to watch the build in behaviour of active links? Do I have to write dedicated MVC-Classes for all the DOM Elements?
There has to be a simpler way, I think. I already created a whole lotta files for such a simple behaviour that I'm thinking I'm totally on the wrong track.
My gut feeling is: That is view logic and the view should just observe a few states in the template and that's it.
What's the leanest approach to the problem?
I don't know if I understand your question right, but why you want to add the class open to the corresponding upper element? It automatically get active assigned. And with correct CSS it should work as expected.
I have created a small example demonstrating what I mean. Please have a look and let me know, if that's the solution for you or what's your problem with this solution.
http://emberjs.jsbin.com/wifusosadega/7/edit
EDIT
Here is a Bootstrap flavored version: http://emberjs.jsbin.com/wifusosadega/9/edit .

Categories

Resources