Using external VueJs components in a VueJS project - ruby-on-rails

I'm trying to use VueStrap in a VueJS project, it looks like webpacker is loading it fine, I can see this in the terminal output, however, when I try use a component from vue-strap I get this error:
[Vue warn]: Property or method "input" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
I tried including the VueStrap as a component in the Vue instance but couldn't get it to work. How do I include the VueStrap into as a component correctly?
Thanks!
This is my application.js:
import Vue from 'vue/dist/vue.js'
import App from '../components/app.vue'
import VueStrap from 'vue-strap'
document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(document.createElement('app'))
const app = new Vue({
el: 'app',
template: '<App/>',
components: { App }
})
console.log('app')
})
This is my app.vue file
<template>
<div id='app'>
<p> {{ message }} </p>
<bs-input :value.sync="input" label="Username" help="Only allows lowercase letters and numbers."
error="Insert username" placeholder="Username can't start with a number." pattern="^[a-z][a-z0-9]+$"
:mask="mask" minlength="5" readonly required icon>
</bs-input>
</div>
</template>
<script>
export default {
data: function () {
return {
message: "Hello World"
}
}
}
</script>
<style scoped>
p {
font-size: 2em;
text-align: left;
}
</style>

Please see the documentation on complication scope, notably:
Everything in the parent template is compiled in parent scope; everything in the child template is compiled in child scope.
Your template includes input and mask properties but your data function does not set those up. They need to be set up and reactive so if they change, Vue can pass them down to the child component (which it looks like your bs-input component exposes an input and mask properties).

Related

Rollup minify classnames

Is there any rollup.js plugins which allow to obfuscate / mangle CSS class names? I haven't found anything, except this one for webpack: https://github.com/sndyuk/mangle-css-class-webpack-plugin
This can be achieved with rollup-plugin-postcss. As per the readme, configuration options for the modules property are passed through to postcss-modules.
Using the generateScopedName property you're able to set the format of the class name:
generateScopedName: "[hash:base64:8]",
There are more examples in the postcss-modules readme including how to generate the name dynamically. Note that you are responsible for ensuring that the names are unique enough to not clash.
The full rollup config would look something like:
import postcss from "rollup-plugin-postcss";
... // other imports
export default {
... // rest of config
plugins: [
... // other plugins
postcss({
...
modules: {
generateScopedName: "[hash:base64:8]",
},
autoModules: true,
}),
...
],
};
Then something like:
.parent {
display: grid;
grid-template-rows: auto 1fr auto;
}
/* styles.module.css */
import STYLES from './styles.module.css';
...
// Use the style however
<div className={STYLES.parent}>
...
</div>
Ends up looking like:
.xSgFDOB2 {
display: grid;
grid-template-rows: auto 1fr auto;
}
<div class="xSgFDOB2">
...
</div>

div tag class attribute contains lot of strings and cannot be replaced with css string definition string

I am trying to develop an UI and the first step is to create CssLayout. Each CssLayout component is added hierarchically with and many CssLayout component.
The problem is when i run the application and inspect the div tags, the class attribute has extra strings that needs to be removed.
<div class="v-csslayout v-layout v-widget .content-container v-
csslayout-.content-container v-has-width v-has-height" style="width: 100%;
height: 100%;"><div class="v-csslayout v-layout v-widget .inner-content-
container v-csslayout-.inner-content-container"></div></div>
and what I need is
<div class=".content-container">
<div class=".inner-content-container">
</div>
</div>
Java Code:
#StyleSheet("{css/spreadjsdefault.css}")
public class SpreadJSWidget extends CssLayout {
/**
*
*/
public SpreadJSWidget() {
super();
addStyleName(".content-container");
CssLayout mainBox = new CssLayout();
mainBox.addStyleName(".inner-content-container");
addComponent(mainBox);
}
spreadjsdefault.css (They are empty for now)
.content-container
{
}
.inner-content-container
{
}
Please advice !
Two things:
In order to be able to properly match the css rules, you have to omit the leading . when adding the style name, i.e. addStyleName("contentContainer"). This way, the css elements will match your style definition.
Css classes like v-csslayout are default classes defined by vaadin used by the default themes to provide a basic layout. They are there by default and can't (and actually shouldnt) be removed entirely. What you can do, however, is to define and overwrite these rules yourself. What's important: Either way, your custom classes will still match when you define them in your style sheet and can overwrite the default theming.

react-rails asset pipeline image path

I'm using the react-rails gem, and I'm having trouble figuring out how to load images from the asset pipeline.
I handle this currently by using the .js.jsx.erb extension, but as far as I know this is unconventional. (am I correct?)
Sometimes I just use an empty div and and set the div's background-image property as the image I intend to use.
What is the best way to go about loading images to react components when using react-rails?
There are three ways to import image...
1) If you are direct using jsx.erb or js.erb file...
var image_path = "<%= asset_path(my_image.png) %>"
OR
render: function() {
return (
<img src={"<%= asset_url('path/to/image.png') %>"} />
)
}
2) Passing as props Through .erb file to .js.erb or .jsx.erb file
in your .erb file
render_component('Component', img_src: image_url('the_path'))
in your .js.erb or .jsx.erb file
render: function() {
return (
<img src={this.props.img_src} />
)
}
3) Recommended: Use .js and .jsx file and render it using view file .html.erb
In view file example.html.erb
<%= react_component("Example", props: {}, prerender: false) %>
In .jsx file Example.jsx
import React, { Component } from "react";
import Image from "<IMAGE_PATH>/image.png";
export default class Example extends Component {
constructor(props, _railsContext) {
super(props);
}
render(){
return(
<div>
<img src={Image} alt="example" />
</div>
)
}
}
You need to register Example component. In your app > javascript > packs > application.js
import ReactOnRails from "react-on-rails";
import Exmaple from "<COMPONENT_PATH>/Exmaple";
ReactOnRails.register({
Exmaple
});
Source: github

Angular 2: How to link form elements across a dynamically created components?

I have a set of form fields that are in a dynamically created component. The parent Component owns the form tag. However, none of the form fields are being added to the Form. I'm using the ComponentFactoryResolver to create the component:
#Component({
selector: 'fieldset-container',
templateUrl: './fieldset-container.component.html',
styleUrls: ['./fieldset-container.component.scss'],
entryComponents: ALL_FIELD_SETS,
})
export class FieldsetContainerComponent<C> {
fieldsetComponent : ComponentRef<any> = null;
#Input() formGroup : FormGroup;
#ViewChild('fieldSetContainer', {read: ViewContainerRef})
fieldsetContainer : ViewContainerRef;
#Output() onComponentCreation = new EventEmitter<ComponentRef<any>>();
constructor(private resolver : ComponentFactoryResolver) {
}
#Input() set fieldset( fieldset : {component : any, resolve : any }) {
if( !fieldset ) return; // sorry not right
// Inputs need to be in the following format to be resolved properly
let inputProviders = Object.keys(fieldset.resolve).map((resolveName) => {return {provide: resolveName, useValue: fieldset.resolve[resolveName]};});
let resolvedInputs = ReflectiveInjector.resolve(inputProviders);
// We create an injector out of the data we want to pass down and this components injector
let injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.fieldsetContainer.parentInjector);
// We create a factory out of the component we want to create
let factory = this.resolver.resolveComponentFactory(findComponentForFieldset(fieldset.component));
// We create the component using the factory and the injector
let component : ComponentRef<any> = factory.create(injector);
// We insert the component into the dom container
this.fieldsetContainer.insert(component.hostView);
// Destroy the previously created component
if (this.fieldsetComponent) {
this.fieldsetComponent.destroy();
}
this.fieldsetComponent = component;
this.onComponentCreation.emit( this.fieldsetComponent );
}
}
The template:
<div #fieldSetContainer [formGroup]="formGroup"></div>
The usage of the dynamic component:
<form class="form" #omaForm="ngForm">
<div *ngFor="let fieldset of page?.fieldsets">
<fieldset-container [fieldset]="{ component: fieldset, resolve: {} }" (onComponentCreation)="onComponentCreation($event)" [formGroup]="omaForm.form"></fieldset-container>
</div>
</form>
I suspect it has something to do with the injector not being hooked up correctly, but from what I can tell it is chained to the parent. I've set a breakpoint in NgModel and it is passed a null for parent which is the problem. I traced that back up into something that looks compiled and it was just hard coding a null. So I'm not sure how that was created with hard coded nulls in there.
Any ideas on how to fix this?
Ok it turns out it has nothing to do with the dynamic nature of this component. I removed it and defined all of my components inline and it still had the problem. The issue was that having form controls inside a Component that were nested within a form tag is just not supported by Angular out of the box. Once you nest a form control in a component it can't see the NgForm anymore which is crazy.
After reading solutions on the web and seeing that no one had a good solution I designed 2 of my own directives that registered the Form into the DI container up at the NgForm, then using DI hierarchy I could inject that into another Directive that would perform the registration below.
Parent Component Template:
<form nested>
<my-component .../>
</form>
Child Component Template:
<div>
<input name="street" [(ngModel)]="address.street" required nest/>
<input name="city" [(ngModel)]="address.city" required nest/>
<input name="state" [(ngModel)]="address.state" required nest/>
<input name="zip" [(ngModel)]="address.zip" required nest/>
</div>
Once I had this in place then I could bring back my dynamic component and it worked perfectly. It was just really hard to get there.
It's really elegant and simple and doesn't require me to pass the form instance down through the layers like so many suggestions on the web show. And the work to register a form control whether it's 1 layer or 999 layers removed is the same.
IMHO NgForm and NgModel should just do this out of the box for us, but they don't which leads to complicated architecture design to accomplish moderately advanced forms.

ERROR chrome_views_delegate.cc(185) -- NOT IMPLEMENTED

Opportunity:
Hello, I have a situation that I simply can't figure-out. I am getting these errors from Dart when I run a quite simple example:
[13288:9212:0320/161303:ERROR:navigation_entry_screenshot_manager.cc(147)] Invalid entry with unique id: 3
[14080:11508:0320/155717:ERROR:chrome_views_delegate.cc(185)] NOT IMPLEMENTED
[14080:11508:0320/155717:ERROR:desktop_root_window_host_win.cc(753)] NOT IMPLEMENTED
[14080:11508:0320/155719:ERROR:desktop_root_window_host_win.cc(753)] NOT IMPLEMENTED
[14080:11508:0320/155747:ERROR:extension_icon_image.cc(201)] Start loading extension icon for Chromium. scale = 1
The messages don't really connect to the Use-Case I'm implementing. My attempts to use debug and other tools have come to not much indeed. I have 'reduced' the problem to a simple example based on the DartPolymer example:
Define a Custom Element tutorial.
This tutorial defines a DartPolymer component called <tut-stopwatch>. In my example I have copied that element as two clones: <x-fred> and <z-fred>. Everything is identical in a diff command, except the names and tags.
The layout of the main index.html page is as follows:
<body>
<x-fred> </x-fred>
<hr/>
<h1>Stopwatch</h1>
<tut-stopwatch> </tut-stopwatch>
<hr/>
<z-fred> </z-fred>
</body>
Investigation so far:
I put a break-point on the DOM register call and the stopwatch creator (constructor):
class TuteStopwatch extends PolymerElement {
#observable String counter='00:00';
TuteStopwatch.created() : super.created();
:
}
The "unique id message" as I call it comes up:
[13288:9212:0320/161303:ERROR:navigation_entry_screenshot_manager.cc(147)] Invalid entry with unique id: 3
During debugging. There's no clear connection to the code executing and I think that this is an async message, unrelated to the registration of the <tut-stopwatch> component.
The other two examples (different in name and a label only): <x-fred> and <z-fred> work fine. It is just the <tut-stopwatch> element that poses a problem.
This is difficult for two reasons:
I have a stand-alone <tut-stopwatch> example working fine.
Despite text and lexical code-compare of three bits of "congruent" code, one is flawed in a specific context. It speaks to a lack of robustness some place.
Obviously I need a bit of direction on where to look for the problem. It reminds me of those games: "One of these things is not like the other . . . "
Thanks in advance.
Code
<tut-stopwatch>
Based on: Define a Custom Element example:
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:async';
import 'package:polymer/polymer.dart';
#CustomTag('tute-stopwatch')
class TuteStopwatch extends PolymerElement {
#observable String counter='00:00';
TuteStopwatch.created() : super.created();
Stopwatch mywatch = new Stopwatch();
Timer mytimer;
:
}
<x-fred>
#CustomTag('x-fred')
//#CustomTag('tute-stopwatch')
class XFred extends PolymerElement {
#observable String counter='00:00';
XFred.created() : super.created();
Stopwatch mywatch = new Stopwatch();
Timer mytimer;
Stopwatch mywatch = new Stopwatch();
Timer mytimer;
:
}
Note: each element is in a different sub-folder and there is no name space collision between on the TuteStopwatch{...} class with <x-fred> and <z-fred>
tut_stopwatch.html
This file is in its own folder with tute_stopwatch.dart:
elements/fred/tute_stopwatch.html
<template>
<style>
:host {
background-color: yellow;
text-align: center;
display: inline-block;
border: solid 1px;
padding: 10px 10px 10px 10px;
}
</style>
<div>
<div> stopwatch:
{{counter}}
</div>
<div>
<button on-click="{{start}}" id="startButton">Start</button>
<button on-click="{{stop}}" id="stopButton">Stop</button>
<button on-click="{{reset}}" id="resetButton">Reset</button>
</div>
</div>
</template>
<script type="application/dart" src="tute_stopwatch.dart"> </script>
fred.html (<x-fred>)
This file is in its own folder with Fred.dart:
elements/fred/fred.html
<template>
<style>
:host {
background-color: blue;
text-align: center;
display: inline-block;
border: solid 1px;
padding: 10px 10px 10px 10px;
}
</style>
<div>
<div> fred:
{{counter}}
</div>
<div>
<button on-click="{{start}}" id="startButton">Start</button>
<button on-click="{{stop}}" id="stopButton">Stop</button>
<button on-click="{{reset}}" id="resetButton">Reset</button>
</div>
</div>
</template>
<script type="application/dart" src="fred.dart"> </script>
github
I have put the failing case on GitHub here:
- https://github.com/aplatypus/dart-experiments
This version fails to show the tute-stopwatch element. Yet clones with a different name work OK. Same code, just different names.
work-around
I can report that I have a work-around. I'm more or less convinced that its a Dart or Dart Editor bug though.
The fix was to manually rename: <tute-stopwatch> to: <x-stopwatch>
The x-stopwatch version of the (same) code then worked a-OK. Then I renamed the custom element back again to:
<tute-stopwatch>
And now the: <tute-stopwatch> is working.
I don't think its a satisfying resolution because I pretty much purged the project folder and Packages cache a couple of times. There be something hanging about me thinks.
Also I'm still seeing odd errors:
F:\.bin\dev\dart\dev\chromium\Chrome.exe --remote-debugging-port=59082 --user-data-dir=C:\Users\william\.dartium --enable-experimental-web-platform-features --enable-html-imports --no-first-run --no-default-browser-check --no-process-singleton-dialog chrome://version/
[18040:16896:0322/210119:ERROR:chrome_views_delegate.cc(185)] NOT IMPLEMENTED
[18040:16896:0322/210119:ERROR:desktop_root_window_host_win.cc(753)] NOT IMPLEMENTED
[18040:16896:0322/210121:ERROR:desktop_root_window_host_win.cc(753)] NOT IMPLEMENTED
When I completely remove the tute-stopwatch element the messages go away, but I still see this:
[18040:16896:0322/210647:ERROR:navigation_entry_screenshot_manager.cc(147)] Invalid entry with unique id: 6
The number for 'unique id' changes from run to run of course.
I figured I'd post the outcome. If you have a similar situation try a different name for the element in question. That may help someone facing similar weirdness.

Resources