I'm just getting started with NativeScript, and am working through the tutorial: https://docs.nativescript.org/angular/tutorial/ng-chapter-3
NativeScript can't find css files in the same directory as my component, even when specifying the moduleId.
// login.component.ts
#Component({
moduleId: module.id,
styleUrls: [
'./login-common.css',
'./login.android.css',
],
templateUrl: './login.html',
})
export class LoginComponent implements OnDestroy { ... }
My directory structure is:
/app
/pages
/login
login.android.css
login-common.css
login.component.ts
login.html
I've wiped the user data from the emulator, stopped/restarted the app, quadruple-checked the files names, but I still get:
Refreshing application... JS: ns-renderer: ERROR BOOTSTRAPPING ANGULAR
JS: ns-renderer: File
/data/data/org.nativescript.Groceries/files/app/pages/login/.login.android.css
does not exist. Resolved from:
/data/data/org.nativescript.Groceries/files/app/pages/login/.login.android.css.
I have also tried not specifying the moduleId value and used paths relative to /app and I get the same errors. No other components use these files. What am I doing wrong?
Update:
I've made another component and was able to successfully import a component-relative stylesheet. Is there some sort of build-cache that I need to clear?
When the tns runtime actually builds your app, it will re-write platform related files.
What this means is that anything .android will just become the root .ts/.css/.html file.
login.android.css becomes login.css
The same goes for iOS related files. This allows you just import the generic file and it will intelligently filter out the correct files for your runtime.
In your example, just import login.css instead of the two style-sheets listed. In your login-android.css file, import the login-common.css file.
EDIT:
In regard to moduleId, I would always recommend applying that your components. It makes the paths relative to the current folder. So if you add it, it will make the './ imports relative to your login component's folder.
Related
Nativescript Angular is well known for its code sharing properties. I am trying to simplify my design by using only 1 typescript file instead of splitting into the .ts and the .tns.ts file.
I was trying to import { Page } from "tns-core-modules/ui/page"; in the .ts. When running on Android, the code works flawlessly, but if I ng serve for the web app, it says Module not found: Error: Can't resolve 'tns-core-modules/ui/page'.
The reason why I wanted to import the page module is because of setting the action bar properties
constructor(private page: Page) {
if (isAndroid) {
console.log("This is Android");
this.page.actionBarHidden = true;
}
}
I was hoping to import the tns-core-modules/ui/page and some other tns-core-modules in the same file as the angular web app. Is it possible to do so? Or is it a must to split into the .ts and the .tns.ts files?
You have to go with platform specific ts files, one for web and one for tns, Page won't be valid while running inside a browser (ng serve).
If you prefer to reuse most of your code, try writting a common / base ts component, extend platform specific ts files from the common / base ts component, inject Page only within the tns specific ts file.
Even though this talks about VueJS. I suspect it will work with any other JavaScript language like Angular or React as well.
I have been learning Vue.js and loving it. Knowing I have a larger application on the way and the fact that I have wanted to start using TypeScript. Now seems like the time to do so. I have a firm grasp on Vue at this point but can not find any documentation (over 2 weeks of finding the exact, MINIMUM requirements) on how to setup TS and actually get it to run.
Here is an example of some HTML and Vue code that works with using just script tags and normal JavaScript.
HTML
<div id="app">
<h4>{{ Value }}</h4>
</div>
#section Scripts {
<script src="~/lib/vue/vue.js"></script>
<script src="~/js/test.js"></script>
}
JavaScript - test.js
var app = new Vue({
el: "#app",
data: {
Value: "Hello there"
}
});
This works and produces Hello there on the page.
Configuring TypeScript
This seems straight forward, I have a TypeScripts folder below my js folder where the "source" .ts files will be. The output files will be in the js folder as .js files. Here is my tsconfig.json located in the TypeScripts folder:
{
"compileOnSave": true,
"compilerOptions": {
"noEmitOnError": true,
"noImplicitAny": false,
"outDir": "../",
"removeComments": false,
"sourceMap": true,
"target": "es5",
"module": "amd" // <-- Should this be used?
},
"exclude": [
"node_modules",
"wwwroot"
]
}
This works and I do get .js files each time a save the .ts files.
However, now I want to incorporate Vue into the .ts using it in ways I have seen in videos as well as code online. The following code compiles without errors:
JavaScript - ES6 - test2.ts
const Vue = require("vue")
const app = new Vue({
el: "#app",
data: {
Value: "Hello there"
}
})
Now I update the HTML to the following:
HTML
<div id="app">
<h4>{{ Value }}</h4>
</div>
#section Scripts {
<script src="~/js/test2.js"></script>
}
I reload the page and all I get is the {{ Value }} markup. Plus the JavaScript error: Uncaught ReferenceError: require is not defined.
That seems simple enough, I figure I just add the following line to the Scripts section and remove the single reference to the test2.js file:
#section Scripts {
<script src="~/lib/require.min.js" data-main="/js/test2.js"></script>
}
Reload and now I get: Uncaught Error: Module name "vue" has not been loaded yet for context: _. Use require([]) which references this but that code now seems to diverge from what the .ts file should look like.
The ES6 Test2.ts file seems to be the way people code. The way it wants me to write the require statement in the link above seems far more verbose and does not show up in any code samples I have seen. So I must be missing something. If it helps, the Vue and Require downloads have come from my package.json (npm) file which looks like this:
"devDependencies": {
"#types/node": "^9.4.7",
"requirejs": "^2.3.5",
"vue": "^2.5.16"
...
}
And my bundleconfig.json which puts them in the wwwroot/lib folders where they should go.
{
"outputFileName": "wwwroot/lib/require.min.js",
"inputFiles": ["node_modules/requirejs/require.js"]
},
{
"outputFileName": "wwwroot/lib/vue/vue.js",
"inputFiles": [ "node_modules/vue/dist/vue.js" ]
}
I have to believe I am so close to getting it. Being able to write code in the more modern ES versions is great. I have just not been able to find the right piece of the puzzle to fit it all together.
The main problem above is because in the first "plain JavaScript" example, you are not using modules at all. You are loading the Vue library directly in your page, which creates the global Vue object, and then your script is global (i.e. not a module) and references the Vue object directly.
For the test2.ts file, you mention this is ES6, but you then 'require' in the Vue library. This means the code is now attempting to use modules, but CommonJS modules, not ES6 modules. (Where you would write something like import Vue from "vue"). This means it would require a loader at runtime (e.g. the require.js library you are trying to use), which could work if configured correctly, but generally you'd want something like WebPack to package up Vue.js and your code into a standalone bundle the page loads at runtime.
Note: Edited paragraph below
I've created a sample ASP.NET Core project showing how to configure TypeScript and WebPack to generate a bundle per page using the global Vue.js object via a script tag. I've put an extensive readme on it to explain all the workings. You can see it at https://github.com/billti/SimpleVueApp . If you have further feedback, I'll continue to update it to make it better/clearer.
That said, as you get deep in Vue there is one Visual Studio limitation to be aware of. Currently there is no rich support for .vue files (known in the docs as "single file components"). What I mean by "rich support", is that these files have a certain context that we don't infer right now to provide good IntelliSense (i.e. completion lists, errors, tooltips, etc.). Also, HTML files in Visual Studio (which is what you would open a .vue files as) also only support plain CSS in <style> tags, and plain JavaScript in <script> tags currently, whereas with the right Vue and WebPack setup you can do things like write LESS code directly in your style tags, and write TypeScript directly in your script tags. My team is looking at this currently and hoping to improve this in the near future.
Let me know if any of that isn't clear. Happy to help further.
I've started with a template from this extension to have a running angular2+ .net core starting point. I didn't want to use boostrap, but materialize-css, so I removed the bootstrap package in package.json, instead I added "materialize-css": "0.98.0",
Then I edited the webpack.config.vendor.js, I removed bootstrap and added materialize-css to the "vendor" list.
Then I rebuilt everything, but it seems that materialize-css is still not present(cannot find its css classes). I tried to clear the browser cache, tried even to open on a brand new browser(edge), but still, no materialize-css classes.
What did I miss?
EDIT
Currently, my vendor list is the following:
vendor: [
'#angular/common',
'#angular/compiler',
'#angular/core',
'#angular/http',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
'#angular/router',
'#angular/platform-server',
'angular2-universal',
'angular2-universal-polyfills',
'materialize-css',
'es6-shim',
'es6-promise',
'jquery',
'zone.js',
]
You're doing everything correctly, just need to do one thing slightly differently. In your webpack.config.vendor.js, instead of materialize-css, add materialize-css/dist/css/materialize.css to the vendor array:
...
entry: {
vendor: {
...
'materialize-css/dist/css/materialize.css',
...
}
}
This will include the css to your resulting bundle. If you also need fonts and js from materialize-css, you'll need to configure appropriate loaders, see https://www.npmjs.com/package/materialize-loader
Sorry for the obfuscated question, I'll elaborate my problem. I am currently developing a single page app in Aurelia, and I found a lib I want to try out: https://github.com/hootsuite/grid. I did the normal jspm routine:
jspm install github:hootsuite/grid
which installs successfully and adds the following to the systemjs config:
map: {
"hootsuite/grid": "github:hootsuite/grid#1.0.0",
The package file looks like this:
define(["github:hootsuite/grid#1.0.0/src/gridList.js"], function(main) {
return main;
});
Which enables me import the module as expected:
import * as grid from 'hootsuite/grid';
So far so good, but the js file referenced by the module is not the one I am interested in (src/gridList.js), the src folder also contains a jquery plugin named "jquery.gridlist.js" which is the file I actually want to resolve. I managed to "fix/hack" it by adding an additional AMD module definition in the module file (grid#1.0.0.js):
define('gridlist', ["github:hootsuite/grid#1.0.0/src/gridList.js"], function(main) {
return main;
});
define(["github:hootsuite/grid#1.0.0/src/jquery.gridList.js", "github:hootsuite/grid#1.0.0/src/gridList.js"], function(main) {
return main;
});
This is not a viable solution because the jspm_modules are not a part of source-control, thus it will have to be patched manually for every dev. So, whats the best approach for this type of problem? Or which features am I missing out on which removes the problem entirely?
I'm new to play, scala, and akka and I am getting an error when using sbt to build it and compiling it by loading localhost in a web browser. The in browser error I'm getting is:
Compilation error
reference to routes is ambiguous; it is imported twice in the same scope by import controllers._ and import models._
In /Users/Louis/Documents/play_actors/app/views/form.scala.html at line 9.
5#main(Html("Calculate Pi")) {
6
7 <h2>Calculate Pi</h2>
8
9 #helper.form(action = routes.Pi.submit) {
10
11 <fieldset>
12 <legend>Pi Options</legend>
I'm not sure why I'm getting this error. I call the html file from Activity.scala:
package controllers
import play.api._
import play.api.mvc._
import views._
object Application extends Controller {
def index = Action {
Ok(html.form(Pi.optionsForm))
}
}
Thanks in advance.
Play generates a number of Scala files including ones based on your routes file and your templates. If you look in the target/scala.2.9.1/src_managed directory after you've attempted to compile your app, you should find a views.html package containing Scala versions of your templates and a controllers package containing a Scala representation of your routes.
As well as a number of Play's own packages, Play templates will automatically import everything in your controllers and model packages. This includes the routes class generated from your routes file, which allows you to reference them in the way you've shown.
I assume that you must have some object or class in your model package which shares the name routes and hence, creates a collision which the compiler can't resolve.