riot jsfiddle breaks when adding a tag function - jsfiddle

This fiddle is broken. Remove the oops function to fix it. What do I do when I need the oops function?
https://jsfiddle.net/mvvapzub/1/
oops(e) {
}
Here is a fiddle that has a riot function (isFolder) and it's not broken.
https://jsfiddle.net/walkermatt/1vdo5pmf/1/

Fixed by indenting everything inside the script tag
https://jsfiddle.net/mvvapzub/3/
/// this does NOT work
<script type="riot/tag">
<app>
<table>
...
</table>
...
oops(e) {
return true
}
</app>
</script>
.
/// this works
<script type="riot/tag">
<app>
<table>
...
</table>
...
oops(e) {
return true
}
</app>
</script>

Related

Why when i pass source manually it works but when i tried to pass source with vuex it doesn't - Vue3 / Vuex / Composition API [duplicate]

I have a case where in my Vue.js with webpack web app, I need to display dynamic images. I want to show img where file name of images are stored in a variable. That variable is a computed property which is returning a Vuex store variable, which is being populated asynchronously on beforeMount.
<div class="col-lg-2" v-for="pic in pics">
<img v-bind:src="'../assets/' + pic + '.png'" v-bind:alt="pic">
</div>
However it works perfectly when I just do:
<img src="../assets/dog.png" alt="dog">
My case is similar to this fiddle, but here it works with img URL, but in mine with actual file paths, it does not work.
What should be correct way to do it?
I got this working by following code
getImgUrl(pet) {
var images = require.context('../assets/', false, /\.png$/)
return images('./' + pet + ".png")
}
and in HTML:
<div class="col-lg-2" v-for="pic in pics">
<img :src="getImgUrl(pic)" v-bind:alt="pic">
</div>
But not sure why my earlier approach did not work.
Here is a shorthand that webpack will use so you don't have to use require.context.
HTML:
<div class="col-lg-2" v-for="pic in pics">
<img :src="getImgUrl(pic)" v-bind:alt="pic">
</div>
Vue Method:
getImgUrl(pic) {
return require('../assets/'+pic)
}
And I find that the first 2 paragraphs in here explain why this works? well.
Please note that it's a good idea to put your pet pictures inside a subdirectory, instead of lobbing it in with all your other image assets. Like so: ./assets/pets/
You can try the require function. like this:
<img :src="require(`#/xxx/${name}.png`)" alt class="icon" />
The # symbol points to the src directory.
source: Vue URL transfrom rules
There is another way of doing it by adding your image files to public folder instead of assets and access those as static images.
<img :src="'/img/' + pic + '.png'" v-bind:alt="pic" >
This is where you need to put your static images:
Your best bet is to just use a simple method to build the correct string for the image at the given index:
methods: {
getPic(index) {
return '../assets/' + this.pics[index] + '.png';
}
}
then do the following inside your v-for:
<div class="col-lg-2" v-for="(pic, index) in pics">
<img :src="getPic(index)" v-bind:alt="pic">
</div>
Here's the JSFiddle (obviously the images don't show, so I've put the image src next to the image):
https://jsfiddle.net/q2rzssxr/
Vue.js uses vue-loader, a loader for WebPack which is set up to rewrite/convert paths at compile time, in order to allow you to not worry about static paths that would differ between deployments (local, dev, one hosting platform or the other), by allowing you to use relative local filesystem paths. It also adds other benefits like asset caching and versioning (you can probably see this by checking the actual src URL being generated).
So having a src that would normally be handled by vue-loader/WebPack set to a dynamic expression, evaluated at runtime, will circumvent this mechanism and the dynamic URL generated will be invalid in the context of the actual deployment (unless it's fully qualified, that's an exception).
If instead, you would use a require function call in the dynamic expression, vue-loader/WebPack will see it and apply the usual magic.
For example, this wouldn't work:
<img alt="Logo" :src="logo" />
computed: {
logo() {
return this.colorMode === 'dark'
? './assets/logo-dark.png'
: './assets/logo-white.png';
}
}
While this would work:
<img alt="Logo" :src="logo" />
computed: {
logo() {
return this.colorMode === 'dark'
? require('./assets/logo-dark.png')
: require('./assets/logo-white.png');
}
}
I just found out about this myself. Took me an hour but... you live, you learn, right? 😊
I also hit this problem and it seems that both most upvoted answers work but there is a tiny problem, webpack throws an error into browser console (Error: Cannot find module './undefined' at webpackContextResolve) which is not very nice.
So I've solved it a bit differently. The whole problem with variable inside require statement is that require statement is executed during bundling and variable inside that statement appears only during app execution in browser. So webpack sees required image as undefined either way, as during compilation that variable doesn't exist.
What I did is place random image into require statement and hiding that image in css, so nobody sees it.
// template
<img class="user-image-svg" :class="[this.hidden? 'hidden' : '']" :src="userAvatar" alt />
//js
data() {
return {
userAvatar: require('#/assets/avatar1.svg'),
hidden: true
}
}
//css
.hidden {display: none}
Image comes as part of information from database via Vuex and is mapped to component as a computed
computed: {
user() {
return this.$store.state.auth.user;
}
}
So once this information is available I swap initial image to the real one
watch: {
user(userData) {
this.userAvatar = require(`#/assets/${userData.avatar}`);
this.hidden = false;
}
}
Here is Very simple answer. :D
<div class="col-lg-2" v-for="pic in pics">
<img :src="`../assets/${pic}.png`" :alt="pic">
</div>
<img src="../assets/graph_selected.svg"/>
The static path is resolved by Webpack as a module dependency through loader.
But for dynamic path you need to use require to resolve the path. You can then switch between images using a boolean variable & ternary expression.
<img :src="this.graph ? require( `../assets/graph_selected.svg`)
: require( `../assets/graph_unselected.svg`) " alt="">
And of course toggle the value of the boolean through some event handler.
<div
v-for="(data, i) in statistics"
:key="i"
class="d-flex align-items-center"
>
<img :src="require('#/assets/images/'+ data.title + '.svg')" />
<div class="ml-2 flex-column d-flex">
<h4 class="text-left mb-0">{{ data.count }}</h4>
<small class="text-muted text-left mt-0">{{ data.title }}</small>
</div>
</div>
You can use try catch block to help with not found images
getProductImage(id) {
var images = require.context('#/assets/', false, /\.jpg$/)
let productImage = ''
try {
productImage = images(`./product${id}.jpg`)
} catch (error) {
productImage = images(`./no_image.jpg`)
}
return productImage
},
I also faced this problem.
Try it:
computed {
getImage () {
return require(`../assets/images/${imageName}.jpg`) // the module request
}
}
Here is a good article that clarifies this:
https://blog.lichter.io/posts/dynamic-images-vue-nuxt/
Tried all of the answers here but what worked for me on Vue2 is like this.
<div class="col-lg-2" v-for="pic in pics">
<img :src="require(`../assets/${pic.imagePath}.png`)" :alt="pic.picName">
</div>
As I am using Gridsome, this way worked for me.
**I also used toLowerCase() method
<img
:src="
require(`#/assets/images/flags/${tournamentData.address.country_name.toLowerCase()}.svg`)
"
/>
well the best and easiest way that worked for me was this of which i was fetching data from an API..
methods: {
getPic(index) {
return this.data_response.user_Image_path + index;
}
}
the getPic method takes one parameter which is the name of the file and it returns the absolute path of the file maybe from your server with the file name simple...
here is an example of a component where i used this:
<template>
<div class="view-post">
<div class="container">
<div class="form-group">
<label for=""></label>
<input type="text" class="form-control" name="" id="" aria-describedby="helpId" placeholder="search here">
<small id="helpId" class="form-text user-search text-muted">search for a user here</small>
</div>
<table class="table table-striped ">
<thead>
<tr>
<th>name</th>
<th>email</th>
<th>age</th>
<th>photo</th>
</tr>
</thead>
<tbody>
<tr v-bind:key="user_data_get.id" v-for="user_data_get in data_response.data">
<td scope="row">{{ user_data_get.username }}</td>
<td>{{ user_data_get.email }}</td>
<td>{{ user_data_get.userage }}</td>
<td><img :src="getPic(user_data_get.image)" clas="img_resize" style="height:50px;width:50px;"/></td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'view',
components: {
},
props:["url"],
data() {
return {
data_response:"",
image_path:"",
}
},
methods: {
getPic(index) {
return this.data_response.user_Image_path + index;
}
},
created() {
const res_data = axios({
method: 'post',
url: this.url.link+"/view",
headers:{
'Authorization': this.url.headers.Authorization,
'content-type':this.url.headers.type,
}
})
.then((response)=> {
//handle success
this.data_response = response.data;
this.image_path = this.data_response.user_Image_path;
console.log(this.data_response.data)
})
.catch(function (response) {
//handle error
console.log(response);
});
},
}
</script>
<style scoped>
</style>
I encountered the same problem.
This worked for me by changing '../assets/' to './assets/'.
<img v-bind:src="'./assets/' + pic + '.png'" v-bind:alt="pic">
The image needs to be transcribed.
What worked for me is putting the images in public folder. i.e public/assets/img
Dynamic Image Tag:
<div v-for="datum in data">
<img
class="package_image"
style="max-width:200px;"
alt="Vue logo"
:src="`./assets/img/${datum.image}`"
>
<div>
I have a solution you may want to try.
Define a method like below
methods: {
getFlagImage(flag){
return new URL('/resources/img/flags/'+flag+'.png', import.meta.url);
},
}
then images can be called with the established for loop
<li :class=" 'nav-item', {'active': language === key} " v-for="(value,
key) in locals" :key="value ">
<a class="dropdown-item" #click="switchLanguageTo(key)">
<img :src="getFlagImage(key)" /> {{value}}
</a>
</li>
I think I found the best solution to this problem by accident!
The only thing you have to do is to start addressing from the root.
Doesn't work
<img :src="'../assets/' + pic + '.png">
Work:
<img :src="'src/assets/' + pic + '.png">
As of today, working with VUE 3 + Typescript & composition API, what I have done is wrap require function in try catch to handle crash.
computed: {
getImage() {
let imgSrc = "";
try {
imgSrc = require(`../assets/weather-widget-icons/ww-icon-${this.weatherForecast.main.toLowerCase()}.svg`);
} catch (error) {
console.error(`Image '../assets/weather-widget-icons/ww-icon-${this.weatherForecast.main.toLowerCase()}.svg' not found!`);
}
return imgSrc;
}
}
and call this function in image tag:
<div class="weather-icon">
<img :src="getImage" :alt="weatherForecast.main" />
</div>

Unable to call Javascript from Blazor. Could not find 'startDataTable' in 'window'

I'm trying to use Blazor and DataTables.net component to add sorting functions to a table. Only the following syntax has allowed me to use Javascript Interop in Blazor:
datatable.js
window.methods = {
startDataTable: function () {
$(document).ready(function () {
$('#table').DataTable();
});
},
showAlert: function () {
alert("waht up");
}
}
The showAlert function is executed when I call it from Blazor component. But if I use the startDataTable function, nothing happens. Is it something missing?
List.razor
#if (!#ToggleList)
{
<table id="table" data-toggle="table" class="table table-responsive" data-sortable="true">
<thead>
<tr>
<th>Key</th>
<th>State</th>
<th data-sortable="true">Graduates</th>
<th data-sortable="true">Exams</th>
<th data-sortable="true">Exams finished</th>
<th data-sortable="true">Percentage</th>
</tr>
</thead>
<tbody>
#foreach (var item in States)
{
<tr>
<td>#item.Icveie</td>
<td #onclick="() => showCz(item.Icveie)">#item.Cdesie</td>
<td>#item.Ucn</td>
<td>#item.Exa_pre</td>
<td>#item.Exa_acre</td>
<td>#item.Porc_acre</td>
</tr>
}
</tbody>
</table>
}
protected override async Task OnInitializedAsync()
{
await JSRuntime.InvokeVoidAsync("methods.showAlert");
}
Index.cshtml
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.23/js/jquery.dataTables.js"></script>
<script src="_framework/blazor.webassembly.js"></script>
<script src="../js/datatable.js"></script>
I'm using Blazor with ASP.NET Core 3.1. My intention is to use DataTables.net component to add extra functions to a table. Any suggestions?
In theory, I think it would be worth to take a look at OnAfterRenderAsync(bool firstrender)
From what I have read, JS is rendered last and therefore cannot be used in OnInitializedAsync.
MS Docs describe this here:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-3.1#after-component-render
From the documentation, Use this stage to perform additional initialization steps using the rendered content, such as activating third-party JavaScript libraries that operate on the rendered DOM elements.
***Disclaimer, I couldn't get this to work for my application. I could only get JS to work within a post-render action like a button-click. But this seems like where MS wants us to go to get JS running at page-load. So I only hope this points you in the right direction.
Note: Also, try to get off of JS where you can. Blazor should have the tools to do what JS is doing.

how to use complex variable as object key in vue data mustache expression?

in a loop, each item is an object. I have to use its value as another object's key.
for vue.js
<html>
<head>
<title>VueJs Introduction</title>
<script type = "text/javascript" src = "https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js">
</script>
</head>
<body>
<div id = "intro" style = "text-align:center;">
<h1>{{ message }}</h1>
<p>{{ jss }}</p>
<table>
<tr v-for="man in lst">
<th>{{ man.name }}</th>
<td>{{jss.man.name}}]</td> <!-- not corrrect -->
<td>{{jss[man.name]}}]</td> <!-- not corrrect too-->
</tr>
</table>
</div>
<script type = "text/javascript">
var vue_det = new Vue({
el: '#intro',
data: {
message: 'My first VueJS Task',
jss: {"n1": 999},
lst: [
{"name": "n1"},
{"name": "n2"}
]
}
});
</script>
</body>
</html>
above cannot work. it plains 'jss.man.name' or 'jss[man.name]' is not a good expression. what I want is 999
You need to understand fundamentally what your code is doing.
When you have an expression of the form first.second, you're roughly requesting that your code retrieve the value named second from the object named first. Note that jss.man.name would then mean "retrieve the value called man from the object jss, and then retrieve the value called name from man". Your object called jss does not contain anything called man, however, so this will return undefined, and undefined definitely does not contain a value named name. In fact, when you try to retrieve the value of a property from undefined, you'll get an error, and when you get an error Vue will make it look like nothing is working at all.
What you're really trying to do is find the value named name in the object named man, and then use this name to retrieve a value from jss. This looks like jss[man.name], which is one of the solutions you have in place. Simply omit the jss.man.name and your code should work:
<html>
<head>
<title>VueJs Introduction</title>
<script type = "text/javascript" src = "https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js">
</script>
</head>
<body>
<div id = "intro" style = "text-align:center;">
<h1>{{ message }}</h1>
<p>{{ jss }}</p>
<table>
<tr v-for="man in lst">
<th>{{ man.name }}</th>
<!--<td>{{jss.man.name}}]</td> commenting this out should fix it! -->
<td>{{jss[man.name]}}</td> <!-- this should be correct-->
</tr>
</table>
</div>
<script type = "text/javascript">
var vue_det = new Vue({
el: '#intro',
data: {
message: 'My first VueJS Task',
jss: {"n1": 999},
lst: [
{"name": "n1"},
{"name": "n2"}
]
}
});
</script>
</body>
</html>
As noted elsewhere, you also had an extra ] being rendered as well. I've removed that in the code snippet above.
You did an extra ] in the end of one way data binding code. You can update the code like
<td>{{jss.man[name]}}</td>
or you can use,
<td>{{jss.man["name"]}}</td>
or,
<td>{{jss.man.name}}</td>

AngularJS route not rendering data

I am trying to implement a very simple angular route. One page only to begin with, will build on once working.
Basically, if I directly display the data in the index.html page, it produces the desired result (count of triples) like so:
Your data looks like this ...
Count of data "records" or "triples": 4585
so I know my queries, factories etc. in themselves are OK.
If I then attempt to implement via a view and route, no data is displayed. Here is my code.
index.html like so:
<!DOCTYPE html>
<head>
<title>Summarisation Min.</title>
<link href="css/main.css" rel="stylesheet"/>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="https://code.angularjs.org/1.2.28/angular-route.min.js"> </script>
</head>
<html>
<h1>Your data looks like this ...</h1>
<body>
<div ng-app="summaryApp">
<div ng-controller="topSummaryCtrl">
<div ng-view></div>
</div> <!-- end topSummaryCtrl controller -->
</div> <!-- end summarryApp module -->
<script src="js/app.js"></script>
<script src="js/controllers/TopSummaryController.js"></script>
</body>
</html>
controller js like so:
app.controller('topSummaryCtrl', function($scope, itemSummary){
itemSummary.success(function(response) {
$scope.itemSummaryResults = response.results.bindings;
});
});
app.factory('itemSummary', function($http){
/* 1 count of data triples */
var query = encodeURIComponent('SELECT (COUNT(*) AS ?no) { ?s ?p ?o }');
var endpoint = "http://localhost:3030/dataset/query";
return $http.get("http://localhost:3030/dataset/query? query="+query+"&output=json&stylesheet=")
});
app js like so:
var app = angular.module('summaryApp',['ngRoute']);
app.config(function($routeProvider){
//set up routes
$routeProvider
.when('/', {
templateUrl: 'partials/count.html',
controller: 'topSummaryCtrl'
})
});
/partials/count.html like so:
<table>
<tr ng-repeat="x in itemSummaryResults">
<td>Count of data "records" or "triples": {{ x.no.value }}</td>
</tr>
</table>
This returns no data. Once I move it out to a separate file to attempt implementation using routes, I can't get the data to display.
I am using Fuseki server on localhost3030 as the SPARQL endpoint and running index.html just by double-clicking on it. I don't know if this might be an issue but have seen conflicting advice online so posting here.
Have spent a couple of days working on this at this stage and still new to Angular so entirely possible it's a dumb error but what? All help gratefully received.
Thanks for reading Hilary.
OK. I have a workaround but to be honest it defeats the purpose of using AngularJS in the first place so I would still like alternative suggestions.
The workaround is to define all JS in a single included JS file or within tags in the HTML and use to implement routing of sorts. The code looks like this (if all in HTML file).
<html>
<head>
<title>HHLDSummaryApp </title>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.min.js"></script>
<script>
var summaryApp = angular.module("summaryApp", ['ngRoute']);
summaryApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/viewCounts', {
templateUrl: 'count.htm',
controller: 'topSummaryCtrl'
}).
otherwise({
redirectTo: '/viewCounts'
});
}]);
/* inject $scope object and data retrieval factories */
summaryApp.controller('topSummaryCtrl', function($scope, itemSummary){
itemSummary.success(function(response) {
$scope.itemSummaryResults = response.results.bindings;
});
});
summaryApp.factory('itemSummary', function($http){
/* 1 count of data triples */
var query = encodeURIComponent('SELECT (COUNT(*) AS ?no) { ?s ?p ?o }');
var endpoint = "http://localhost:3030/dataset/query";
return $http.get("http://localhost:3030/dataset/query?query="+query+"&output=json&stylesheet=")
});
</script>
</head>
<body>
<h2>Your Data Looks Like This ... </h2>
<div ng-app="summaryApp">
<div ng-view></div>
<script type="text/ng-template" id="count.htm">
<table>
<tr ng-repeat="x in itemSummaryResults">
<td>Count of data "records" or "triples": {{ x.no.value }} </a></td>
</tr>
</table>
</script> <!-- end viewCounts -->
</div>
</body>
</html>
As I said, this workaround essentially defeats the purpose of using angular as we only use it for the ng-repeat functionality so please suggest alternative solution if you can. Thanks.

ASP.NET MVC4 and Knockout js

I am trying to use knockout js in my project so I tried the simple Hello World example but i couldnt get it to work. I created a new MVC4 project and just copy do a simple binding below is my code
<script src="~/Scripts/knockout-2.1.0.js" type="text/javascript"></script>
<script type="text/javascript">
// Here's my data model
var viewModel = function (first, last) {
this.firstName = ko.observable(first);
this.lastName = ko.observable(last);
//this.fullName = ko.computed(function () {
// Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName.
//return this.firstName() + " " + this.lastName();
//}, this);
};
$(document).ready(function() {
ko.applyBindings(new viewModel("Planet", "Earth")); // This makes Knockout get to work
});​
</script>
<div class="liveExample">
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
#*<h2>Hello, <span data-bind='text: fullName'> </span>!</h2>*#
</div>
Basically it will just display the value of the model on a textbox.
I already referenced the knockout.js in my project but it does not work
I also added the knockout js in my BundleConfig.cs
bundles.Add(new ScriptBundle("~/bundles/knockout").Include("~/Scripts/knockout-2.1.0.js"));
I didnt work
If you are using MVC, use the scripts section to declare your JS. This will move the declarations to the bottom of the HTML page, letting the HTML render first. Here's my version of your code that worked first time out of the box:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div class="liveExample">
<p>First name:
<input data-bind="value: firstName" /></p>
<p>Last name:
<input data-bind="value: lastName" /></p>
#*<h2>Hello, <span data-bind='text: fullName'> </span>!</h2>*#
</div>
#section scripts {
<script src="~/Scripts/knockout-2.2.1.js"></script>
<script type="text/javascript">
var viewModel = function (firstName, lastName) {
this.firstName = ko.observable(firstName);
this.lastName = ko.observable(lastName);
};
$(function () {
ko.applyBindings(new viewModel("Planet", "Earth"));
});
</script>
}
try putting knockout in the of your document. Without any error messages the only thing I can say is I ran into a similar problem and that was the fix for me.
My example was driving me crazy because it worked in fiddle but not in MVC, I mentioned it to a designer friend of mine and he said it made since to him, basically that knockout needed to be fully downloaded before the page began to render.
Hope this helps