AngularJS Material Dialog using component as template - css

I have an angular component which I want to use in an AngularJS Material dialog:
return $mdDialog.show({
template: '<publish-dialog user="$ctrl.user" target-collection="$ctrl.targetCollection"></publish-dialog>',
controller: function () {
this.user = user;
this.targetCollection = targetCollection;
},
controllerAs: '$ctrl',
targetEvent: event,
clickOutsideToClose: true
});
The problem is, that when defining the template like this, the generated html looks like this:
<md-dialog>
<publish-dialog>
<md-toolbar></md-toolbar>
<md-dialog-content></md-dialog-content>
<md-dialog-actions></md-dialog-actions>
</publish-dialog>
<md-dialog>
The component element is breaking the between md-dialog and md-toolbar, md-dialog-content and md-dialog-actions leads to a layout break and the md-toolbar and the md-dialog-actions are not fixed.
So my question is, is there a way to only render the component template contents without the component element (<publish-dialog></publish-dialog>)?

In your directive, try using replace: true.
From How to use `replace` of directive definition?

Related

Material-UI - why different css is shown on prod environment then development env

I use material UI (verison: ^4.12.3) Select, with custom input.
For some reason the prod env Select input has a black background and :before element with white background.
I don't know from where it comes from.
this is image of the prod:
this is image of the dev Select:
when comparing the 2 css & html of the envs Select element, it's is shown that there is a ::before element added in prod that is not presented in dev
also, the background color is different. in prod there is another class added to the InputBase element, which doesn't exist in dev. this class adds a background-color black:
Edit 1
it seems like MUI inject <style>. in the prod html i see the background-color: black and the ::before. ill try adding the index solution, but my problem is not precedence (the style that i do use override the injected style). also, it wont help the ::before element. how to disable the injected styles ? or work around it ?
the injected bad css:
Please refer to this question. As answered by user Mordechai.
It seems like webpack could mess with MUI's rules on JSS precedence... This could be solved by adding an index of one to MUI's methods.
//Hook
const useStyles = makeStyles({
// your styles here
}, {index: 1})
// HOC
MyComponent = withStyles({
// your styles here
}, {index: 1})(MyComponent)
adding <StylesProvider /> wrapper to the app fixed it. we use micro-frontend infrastructure. and one of the frontends app also had makeStyles. this is causing classNames conflicts in MUI.
in the root component <App/>:
import {
StylesProvider,
createGenerateClassName
} from '#material-ui/core/styles';
const generateClassName = createGenerateClassName({
seed: 'app1'
});
const App = () => {
return (
<StylesProvider generateClassName={generateClassName}>
<OtherAppComponents />
</StylesProvider>
)
}
if you have more then 2 add a provider and a generator to each, with different seed

Change css variables dynamically in angular

In my angular project, I have some css variables defined in top level styles.scss file like this. I use these variable at many places to keep the whole theme consistent.
:root {
--theme-color-1: #f7f7f7;
--theme-color-2: #ec4d3b;
--theme-color-3: #ffc107;
--theme-color-4: #686250;
--font-weight: 300
}
How can I update values of these variables dynamically from app.component.ts ? And What is the clean way to do this in angular ?
You can update them using
document.documentElement.style.setProperty('--theme-color-1', '#fff');
If u want to update many values, then create a object
this.styles = [
{ name: 'primary-dark-5', value: "#111" },
{ name: 'primary-dark-7_5', value: "#fff" },
];
this.styles.forEach(data => {
document.documentElement.style.setProperty(`--${data.name}`, data.value);
});
The main thing here is document.documentElement.style.setProperty. This line allows you to access the root element (HTML tag) and assigns/overrides the style values.
Note that the names of the variables should match at both places(css and js files)
if you don't want to use document API, then you can use inline styles on HTML tag directly
const styleObject = {};
this.styles.forEach(data => {
styleObject[`--${data.name}`] = data.value;
});
Then In your template file using ngStyle (https://angular.io/api/common/NgStyle)
Set a collection of style values using an expression that returns
key-value pairs.
<some-element [ngStyle]="objExp">...</some-element>
<html [ngStyle]="styleObject" >...</html> //not sure about quotes syntax
Above methods do the same thing, "Update root element values" but in a different way.
When you used :root, the styles automatically got attached to HTML tag
Starting with Angular v9 you can use the style binding to change a value of a custom property
<app-component-name [style.--theme-color-1="'#CCC'"></app-component-name>
Some examples add variables directly to html tag and it seem in the element source as a long list. I hope this helps to you,
class AppComponent {
private variables=['--my-var: 123;', '--my-second-var: 345;'];
private addAsLink(): void {
const cssVariables = `:root{ ${this.variables.join('')}};
const blob = new Blob([cssVariables]);
const url = URL.createObjectURL(blob);
const cssElement = document.createElement('link');
cssElement.setAttribute('rel', 'stylesheet');
cssElement.setAttribute('type', 'text/css');
cssElement.setAttribute('href', url);
document.head.appendChild(cssElement);
}
}

Css Selector in Framework7 vue

i try to build an Cordova/Phonegap application using vue.js and the Framework7.
I find out how to use functions like "onClick" using the "v-on:click="OnClick" attribute in an html element. Framework7 has jquery already implemented in the dom.
But there is one question. How can i access the dom directly, so that i can select whole css classes with the jquery selector. Like:
$('.likeButton'). ?
In the offical framework7 i found something like this to access the dom with its functions:
this.$$ or this.Dom7
This is what i have already written down in the home.vue file:
<script>
//import Fonts-awesome Icons
import FontAwesomeIcon from '#fortawesome/vue-fontawesome'
import {} from '#fortawesome/fontawesome-free-solid'
import F7Icon from "framework7-vue/src/components/icon";
import F7PageContent from "framework7-vue/src/components/page-content";
import * as Framework7 from "framework7";
export default {
name: 'FAExample',
components: {
F7PageContent,
F7Icon,
FontAwesomeIcon
},
methods: {
clickit: function () {
console.log("hi");
//this is what i have tested, looking if i have access to dom
let $$ = this.$$;
console.log($$);
},
//this is what i want to use
$('.likebutton').on('click',function () {
})
}
}
</script>
Did any of you have an idea how this works?
I hope you can help me. I'm new with vue.js in combination with the framework7.
Thank's for your help :)
We can use all the DOM functions just like
this.$$('.classname)
for example, if you want to hide something by jquery you can use as:
this.$$('.classname).hide()
To check all the DOM functions you can check the official documentation.
https://framework7.io/docs/dom7.html
But make sure that your DOM function should not in any Window function.
If you get the error to implemented it, just make the 'this' instance first.
Just like:
var self=this; // a global variable with this instance
use
self.$$('.classname).hide()
for any framework7 help, just ping me on skyp: sagardhiman5_1
Have you tried using Vue's $refs? You can set a reference to a specific DOM element and then access that in Vue.
A simple example:
<template>
<div class="some-item" ref="itemRef">Some item</div>
</template>
Then in the component:
var myItem = this.$refs.myItem;
// do what you want with that DOM item...
You can also access $refs from the parent. The example in the link below gives details on that.
More on $refs: https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs

Vue 2.0 Laravel 5.3 Parent Child relationship with slot

I have a project where when i click on a anchor on parent item-sorting-list a property of child item-card will change so it sort something out based on that property. However the data does not seem to pass to the child. I am wondering if there is anything wrong when i built up the parent child relationship in the meanwhile?
template (item-sorting-list)
<a :name="subcat.name" href="" #click.prevent="getSelectedSubcat(subcat.name)">{{subcat.name}}</a>
methods (item-sorting-list)
methods: {
getSelectedSubcat(subcat){
var vm = this;
vm.selectedSubcat = subcat
}
}
When I click on the subcat.name, it does actually store subcat.name into selectedSubcat (verified from Vue devtool) in the item-sorting-list component. The problem is item-card does not store it even though i put selectedSubcat as props
HTML (does this work as parent child relationship here?)
<item-sorting-list><item-card></item-card></item-sorting-list>
UPDATED item-card
export default {
props:[
'selectedSubcat'
],
data(){
return {
products:[],
}
},
mounted() {
this.getAllProducts()
},
methods: {
getAllProducts(){
var vm = this;
vm.$http.get('/getProducts').then((response)=>{
vm.products = response.data.data.products;
});
}
}
}
from Vue devtool, item-card is included in the item-sorting-list, I would say that means they are parent child relationship? but then when i click something in item-sorting-list and change selectedSubcat, selectedSubcat in item-sorting-list does change but the selectedSubcat in item-card remains undefined. Sorry for my bad English.
UPDATE2
I notice that every example that I found online is that they set selectedSubcat in the new Vue with el="#app" in it instead of any other component (in my case item-sorting-list). Does that matter? I feel like the :selected-subcat="selectedSubcat in
<item-sorting-list>
<item-card :selected-subcat="selectedSubcat"></item-card>
</item-sorting-list>
cannot read the selectedSubcat that I defined in the component item-sorting-list but instead if i set selectedSubcat in the following
const app = new Vue({
el: '#app',
data:{
selectedSubcat:1
}
});
it does read selectedSubcat as 1. So what I would say is that item-card does not consider item-sorting-list as its parent. But why and how can I make it to become item-card's parent? [NOTE: but in the Vue devtool the tree does show that item-sorting-list does consist of item-card, item-card does show after clicking the arrow on the left of item-sorting-list]
In VueJs, you have parent child relation, when you don't register a vue component globally, but you make a component available only in the scope of another instance/component by registering it with the components instance option, like following:
var Child = {
template: '<div>A custom component!</div>'
}
new Vue({
// ...
components: {
// <my-component> will only be available in parent's template
'my-component': Child
}
})
In your case, I dont see selectedSubcat being passed as dynamic props to child component item-card. Dynamic props to data on the parent ensures whenever the data is updated in the parent, it will also flow down to the child:
You probably have to pass it to child like following:
<item-sorting-list>
<item-card :selected-subcat="selectedSubcat"></item-card>
</item-sorting-list>
You also have to add props in your item-list like this:
var itemList = {
props: ["selectedSubcat"]
template: '<div>Yout component!</div>'
}
notice I have converted it to kebab-case, because HTML being case-insensitive, camelCased prop names need to use their kebab-case (hyphen-delimited) equivalents(Documentation).

Meteor React - Why are React Components defined differently in React Mounter vs React Layout from Kadira?

I am looking forward to Meteor 1.3 so I can import React components instead of having them as globals.
Been following this tutorial (https://voice.kadira.io/getting-started-with-meteor-1-3-and-react-15e071e41cd1) and I noticed I will have to use React-mounter instead of React-Layout from Kadira
In these docs here:
https://github.com/kadirahq/react-mounter
I see that the React components are defined like this:
const MainLayout = ({content}) => (
<div>
<header>
This is our header
</header>
<main>
{content}
</main>
</div>
);
Instead of something like this
MainLayout = React.createClass({
propTypes: {
content: React.PropTypes.element
},
render() {
return (
<div>
<header>
This is our header
</header>
<main>
{this.content}
</main>
</div>
);
}
});
Can you help explain to me what is happening here? Also how do I use this new style? Where to define all the properties, methods, mixins, etc?
Also as a side question, I noticed React was added as an npm package, instead of using Meteor add react. Is this how we are supposed to add react now?
You could categorize your components in two types: containers and presentational components.
For more details see this
React v0.14 introduced something called functional components which are presentation components that are created via a function instead of a class instance.
Since they are presentational components they are not intended to have more methods or mixins or anything, they just display data.
If you want to stick with React v0.14 and ES2015 you could create your components like
class Component extends React.Component {
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps', nextProps.data.bar);
}
render() {
return <div>Bar {this.props.data.bar}!</div>;
}
}
You now have a full component that can have state, other event handlers and other methods.
A very important thing to note here is that the ES2015 syntax does not allow mixins because they prefer inheritance or functional composition.
Hope that helps!
Sorry I can't help you with your side question, haven't use React with Meteor.

Resources