Can we append angular material form fields within a div? - javascript

I have a div tag and I want to append the angular material form fields inside that div. The problem is it's not rendering that tags. Can we do this using any method?
enter image description here

The angular way is has an array of object, e,g.
data=[{placeholder:"Enter Name",label:"Name"},
{placeholder:"Enter surname",label:"Surname"}]
and make some like
<mat-card *ngFor="let item of data">
<div class="row">
{{item.label}}<input mat-input [placeholder]="item.placeholder">
</div>
</mat-card>

When you are using angular, never manipulate the DOM manually (via native DOM APIs or jQuery).
When you are using a component or a directive in an angular template (ie. the html of your component), that is not real html, that is transformed to javascript. So when the application is running, where you wrote <mat-car> in you template and you also see <mat-card> in the DOM, that was actually put there by the code generated by angular, but a lot other things also happened (ie. the mat-card component was initialised).
When you just put the components selector manually into the DOM, nothing will happen, because the component is not initialised. To make it work, you have to use the material components from another components' template. Further reading: https://angular.io/guide/architecture-components
Suggestion: don't even import jQuery into the project at all, that way you won't even be tempted to do this.

Related

alpinejs : limitations on usage of x-on directive

It seems to me like the x-on directive does not work without the presence of an x-data directive on a parent element.
For example, the below does not work
<button
x-on:click='console.log("hello")'>
left
</button>
It needs to be converted as following for it to work
<div x-data="{}">
<button
x-on:click='console.log("hello")'>
left
</button>
</div>
If I am understanding it correctly and an x-data directive is necessary, why would it be that way?
The x-data directive is required because of the main philosophy of Alpine.js framework.
With a full SPA (single page application) framework, like Vue.js, the main index.html file usually has only a single empty element inside <body>, like <div id="app"></div>. Then we mount our Vue.js application to the #main element and Vue.js takes over the entire frontend. After that by default everything is assumed to be a Vue.js component, like <MyComponent :some-data="42"></MyComponent>, so we don't have to mark them in any other way.
However, Alpine.js follows a different path. It is not intended to be a full SPA framework, like Vue.js. Its main purpose is to "enhance" frontend markup code generated by a backend framework like Django/Laravel/etc (the author of Alpine.js, Caleb Porzio, is the author of Laravel Livewire). So here by default a <button> element is assumed to be a normal button, not an Alpine.js component, therefore Alpine.js does not scan it for Alpine.js specific attributes, like x-on. We have to add the x-data attribute to an HTML element like <button> to mark it as an Alpine.js component. After that Alpine.js scans for directives as such, and takes over the handling of the marked element. This method works well with backend frameworks, where we usually only want to make some elements interactive on the frontend with Alpine.js, but any other logic is handled by the backend.
Nevertheless, if you want you can add an empty x-data attribute to the main <div> element in your markup, that makes Alpine.js work as an SPA framework, so it will scan every element for Alpine.js specific attributes. That's totally fine if you want to use Alpine.js this way. But usually we can define smaller, reusable components, so we put the x-data={} attribute to the specific element or to closest ancestor of the element.

How to parse a html string to native angular template

Currently I'm rendering the html string using innerHtml property after bypassing the angular sanitizing mechanism this is working for rendering the contents. But not able to map the event handlers to a function in angular component.
E.g.the html string will contain a button like below
<button (click)="callme()">Click</button>
the callme function will be part of angular component file. I want this click event to be handled in angular function.
Is it possible to parse this string to html dom and handle the events in angular components.
Sample code which describes this scenario and using angular cdk Portals.
https://stackblitz.com/edit/angular-upaudh?file=src%2Fapp%2Fcdk-portal-overview-example.ts
There are 2 ways that you can implement it, it depends from what you want.
The easy way is to use innerHtml input like this:
HTML
<div [innerHTML]="htmlStr"></div>
TS
htmlStr: 'Hello';
If you want to create a dynamic template that will be translated to HTML at build time. Then you have to go with Portals.
PS: In your example (in the comments) you use [innerHtml] and try to bind it in a Portal. Again [innerHtml] will not be translated before runtime so your click event will not be in the same scope as your component. The thing that you ask is an open conversation in github: Issue. For now you can use the alternatives above to solve your case. You can use innerHtml, and then use renderer2 or native element reference to bind click events to your functions, after they have rendered on the view.

Add arbitrary Vue.js components to parent component

I'm using Vue.js to build ui for my html5 game. I have a case where I want to define ui-containers which essentially just group other ui-components and position them to somewhere on screen. So I could have something like this going on:
<ui-container>
<ui-component1></ui-component1>
<ui-component2></ui-component2>
<ui-component3></ui-component3>
</ui-container>
Where I need to add and remove those components dynamically based on data-model which represents the content of the container. The problem is that I'd like to keep ui-container generic, so that I can append any Vue-component to it without having information in template about which components there might be.
I googled and found this example which concerns injecting components dynamically: http://forum.vuejs.org/topic/349/injecting-components-to-the-dom
While the data-driven version in example was easy to make and understand, it uses v-for for tag and therefore requires one to know before hand the type of child-component.
So question is, how I can generalize that example to work with any component dynamically? Should my data-model have the type of component or tag name of it and then interpolate it in v-for? Or is there existing mechanism for this kind of requirement?
You can use special is attribute to dynamically set the type of a component. Here are the docs. The code will look somewhat like:
<div id="app">
<div v-for="component in components" :is="component.type" :value="component.value"></div>
</div>
Working fiddle to play with: Dynamic Vue.js components

Polymer elements within angular 2 component

I have a set of custom polymer elements, that I would like to use within an angular 2 application.
It seems like there's a problem concerning the content tag of the polymer element. The content of the element gets rendered at the wrong place within the polymer element, if the element is located within an angular 2 component.
Example:
The template of my polymer element "my-button" looks like this:
<template>
<button>
<content></content>
</button>
</template>
Use outside angular
When I use this element outside of my angular 2 component, I get the result that I expected:
Use:
<my-button>Foo</my-button>
Result:
<my-button>
<button>
Foo
</button>
<my-button>
Use within angular 2 component
When used within an angular 2 component, the content always gets rendered at the end of the elements template. Just like the content tag didn't exist.
Use:
<my-button>Foo</my-button>
Result:
<my-button>
<button>
</button>
"Foo"
<my-button>
Question
The problem might be, that polymer and angular 2 both use the content tag for transclution. So maybe things get a little messy when using both together.
I would love to use all of my polymer elements inside angular 2. So any ideas on how to fix this would be very much appreciated.
There are a few open issue about Angular2 combined with Polymer. For example Angular doesn't use Polymer.dom(el)... for manipulating a Polymer elements children. This is probably what breaks your components.
A workaround is to enable full shadow DOM and polyfills. See https://www.polymer-project.org/1.0/docs/devguide/settings.html
An issue I haven't found a solution yet is passing <template>s (like required for example for <iron-list>. Angular handles templates on its own and doesn't pass it to the Polymer element.
There is a ngNonBindable directive. I haven't tried it yet on the <template ngNonBindable> myself but it might work. I tried it seems that's only to ignore [prop]="field"/prop="{{field}} bindings.
Another issue is with <style is="custom-style">. They can only be added in the <head> element or within Polymer elements, but not to Angular components.
See also Two-way binding in Angular 2 with NgModel and mutating bound property?
Check out https://www.npmjs.com/package/#vaadin/angular2-polymer, which should resolve most issues in integrating Polymer elements to Angular 2.
User guide: https://github.com/vaadin/vaadin-core-elements/blob/master/docs/angular2.adoc
Tutorial (draft): https://github.com/vaadin/angular2-polymer/blob/d4581e8fd82841eea84ef40e16e262a12ee4b082/docs/tutorial.adoc
Better shady DOM support is waiting to be merged from a separate branch (should be merged and released within two weeks): https://github.com/vaadin/angular2-polymer/tree/feature/polymer-dom-adapter
It would be great if you could try it out and see if it works for you!
Eventually, the documentation will be published at https://vaadin.com/docs/

Angular 1.4: Add directives dynamically to markup

I have a web application thats written mostly in Jquery, that is essentially a dashboard that a user can add any number of custom widgets to. I have the users currently added widgets, so when its loaded up I masically append each widget to the DOM. I want to work on converting this to an Angular application however im stumbling on one major issue.
1)I can recreate each widget as a directive, that will work nicely. However what I'm struggling with is how to add each widget that a user has setup on load. My first attempt at solving this was to create a generic widget directive, and doing an ng-repeat, and dynamically assigning the widget its controller/templateUrl.
In theory this seems great however I ran into some issues with not being able to dynamically pass the controller name via attribute. if I hard coded a string value it would work, but wouldnt a data-bound attribute in the ng-repeat. Example below does not work.
<quidget ng-dynamic-controller="quidget.QuidgetName" ng-repeat="quidget in tab.quidgets track by $index"></quidget>
if instead of quidget.QuidgetName I passed in the actual name of the controller, it would work...like so
<quidget ng-dynamic-controller="quidget1Controller" ng-repeat="quidget in tab.quidgets track by $index"></quidget>
Does anyone have any insight on how I can go about accomplishing this?
Instead of passing the controller name dynamically to the directive you can define the name of the controller in the template of that widget (this is assuming that every widget has a different template). For example you just pass the widget name to the controller:
<quidget ng-repeat="quidget in quidgets" name="quidget.name">
Next, in your quidget directive's template you conditionally load the template based on the name of the widget, some thing like this:
<div ng-switch on="name">
<div ng-switch-when="widget1" >
<ng-include src="'widget1.html'"></ng-include>
</div>
<div ng-switch-when="widget2" >
<ng-include src="'widget2.html'"></ng-include>
</div>
</div>
and inside each widget's template you define the Controller name like this:
<p ng-controller="widget1Ctrl">This is widget1.</p>
Here is a working plunker that illustrates the whole idea: http://plnkr.co/edit/dBqHRqChy17U8pFI9PXH
I know it's kind of a messy solution and I am pretty sure this can be accomplished in a much simpler manner.

Categories

Resources