asp.net-mvc: symbole de rasoir '@' dans le fichier js

90

J'ai un .csHtmlfichier -razor avec une fonction javascript qui utilise la @Url.Contentfonction C # à l'intérieur pour l'URL ajax.
Je souhaite déplacer cette fonction vers un .jsfichier référencé de ma vue.

Le problème est que javascript ne "connaît" pas le @symbole et n'analyse pas le code C #.
Existe-t-il un moyen de référencer des .jsfichiers depuis une vue avec le symbole "@"?

gdoron soutient Monica
la source
2
Peut-être que cela aide (voir la réponse) stackoverflow.com/questions/7892793/ajax-succes-function
Andriy Khrystyanovich

Réponses:

87

Vous pouvez utiliser des data-*attributs HTML5 . Supposons que vous souhaitiez effectuer une action lorsqu'un élément DOM tel qu'un div est cliqué. Alors:

<div id="foo" data-url="@Url.Content("~/foobar")">Click me</div>

puis dans votre fichier javascript séparé, vous pouvez travailler discrètement avec le DOM:

$('#foo').click(function() {
    var url = $(this).data('url');
    // do something with this url
});

De cette façon, vous pourriez avoir une séparation pure entre le balisage et le script sans jamais avoir besoin de balises côté serveur dans vos fichiers javascript.

Darin Dimitrov
la source
Merci. Je pense que plusieurs valeurs peuvent être un casse-tête. Tout d'abord, j'ai pensé que cela pouvait résoudre mon problème, mais après avoir essayé, j'ai trouvé tellement de références dans mon code et j'ai décidé de trouver un autre moyen.
QMaster
19

Eh bien, je viens de trouver un moteur de rasoir sur nuget qui le fait! Le sens résout la @syntaxe!
Son nom est RazorJS .

Le paquet Nuget


Mise à jour 2016:
le package n'a pas été mis à jour pendant 5 ans et le lien du site du projet est mort. Je ne recommande plus aux gens d'utiliser cette bibliothèque.

gdoron soutient Monica
la source
Pouvez-vous examiner cela? stackoverflow.com/questions/27702322/…
iamCR
Premier lien cassé
Memet Olsen
@MemetOlsen, en effet, désolé mais je ne trouve pas de copie, alors je l'ai supprimé :(
gdoron soutient Monica
@gdoron, pas de problème. Je voulais juste vous faire part du lien mort. Comme vous l'avez dit, le package n'a pas été mis à jour depuis 5 ans, c'est donc probablement une mauvaise idée de l'utiliser de toute façon.
Memet Olsen
10

Une façon d'aborder le problème est:

Ajout d'une vue partielle avec les fonctions javascript à la vue.
De cette façon, vous pouvez utiliser le @symbole et toutes vos javascriptfonctions sont séparées de la vue.

gdoron soutient Monica
la source
9

Vous avez deux options:

  • Utiliser la valeur comme paramètre dans la fonction et câbler dans la vue
  • Créez un espace de noms (au lieu d'une variable de niveau public qui est considérée comme une mauvaise pratique dans JS) et définissez cette valeur en haut de la page, puis utilisez-la dans votre js

Par exemple:

 var MyCompany = 
 {
   MyProject: {
                  MyVariable:""
               }
  };

Et puis à votre avis, définissez-le:

MyCompany.MyProject.MyVariable = @....

METTRE À JOUR

Vous pourriez vous demander qu'aucun n'est bon à cause du couplage, eh bien c'est vrai, vous couplez js et view. C'est pourquoi les scripts doivent ignorer l'emplacement dans lequel ils s'exécutent, c'est donc le symptôme d'une organisation non optimale des fichiers.

Quoi qu'il en soit, il existe une troisième option pour créer un moteur de visualisation et exécuter les fichiers js contre le rasoir et renvoyer les résultats. C'est plus propre mais beaucoup plus lent donc pas recommandé non plus.

Aliostad
la source
1
+1 Je fais la première méthode. Appelez une fonction d'initialisation à partir de votre vue en passant toutes les données dont vous avez besoin.
Richard Dalton
Merci, la deuxième approche n'est pas un mauvais couplage entre la vue et le fichier js? Avez-vous un meilleur moyen?
gdoron soutient Monica
Les deux se couplent. Il n'y a aucun moyen de découpler à moins que vous n'écriviez un moteur de vue pour traiter les fichiers js avant le rendu. Voir mes mises à jour.
Aliostad
qu'en est-il de cette façon que j'ai suggérée? stackoverflow.com/questions/7902213/…
gdoron soutient Monica
Ça a l'air bien. Mon +1. La vue partielle ou complète ne change rien. C'est toute la vue de couplage avec js.
Aliostad
7

Afin d'obtenir la @variable dans votre fichier .js, vous devrez utiliser une variable globale et définir la valeur de cette variable à partir de la vue mvc qui utilise ce fichier .js.

Fichier JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

Fichier MVC View:

<script language="text/javascript">
    myValue = @myValueFromModel;
</script>

Assurez-vous simplement que tous les appels à votre fonction se produisent APRÈS que la valeur ait été définie par la vue.

Joël Etherton
la source
1
qu'en est-il de passer directement myValue comme paramètre à la fonction? Je préfère avoir des appels explicites avec param plutôt que de compter sur des globaux, mais je ne suis pas tellement fan de javascript, donc je manque peut-être un aspect important d'avoir un global.
BigMike
@BigMike: Certainement acceptable. La méthode que j'ai présentée ci-dessus rend simplement la variable disponible pour plusieurs fonctions simultanément, mais l'utilisation de paramètres est tout aussi bonne.
Joel Etherton
Merci pour la clarification. Ce serait génial d'avoir une sorte de version d'objet js du modèle automatiquement (via Attributes dans la classe de modèle sera génial), cela ajoutera simplement un modèle et une solution de variable entièrement consciente de l'espace de noms. Je suppose que le gros problème serait de savoir comment injecter le code dans le html généré envoyé au navigateur (directement via la balise <script>). Je pense que je vais faire quelques expériences là-dessus dès que mon projet actuel sera terminé.
BigMike
@BigMike: Cela devrait être assez facile à réaliser en utilisant la classe DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ). Cela créerait une version JSON de votre classe qui pourrait être analysée dans la vue.
Joel Etherton
4

Ce n'est probablement pas la bonne approche. Considérant la séparation des préoccupations. Vous devriez avoir un data injectorsur votre JavaScriptclasse et qui est dans la plupart des cas des données JSON.

Créez un fichier JS dans votre scriptdossier et ajoutez cette référence à votreView

<script src="@Url.Content("~/Scripts/yourJsFile.js")" type="text/javascript"></script>

Maintenant, considérez une JavaScriptclasse littérale dans votre yourJsFile.js:

var contentSetter = {
    allData: {},
    loadData: function (data) {
        contentSetter.allData = eval('(' + data + ')');
    },
    setContentA: function () {
        $("#contentA").html(allData.contentAData);
    },
    setContentB: function () {
        $("#contentB").html(allData.contentAData);
    }
};

Déclarez également une classe

public class ContentData
{
    public string ContentDataA { get; set }
    public string ContentDataB { get; set }
}

Maintenant, Actionfaites ceci:

public ActionResult Index() {
    var contentData = new ContentData();
    contentData.ContentDataA = "Hello";
    contentData.ContentDataB = "World";
    ViewData.Add("contentData", contentData);
}

Et de votre point de vue:

<div id="contentA"></div>
<div id="contentB"></div>

<script type="text/javascript">
    contentSetter.loadData('@Json.Encode((ContentData) ViewData["contentData"])');
    contentSetter.setContentA();
    contentSetter.setContentB();
</script>
Abdul Munim
la source
Agréable! mais je pense que c'est trop compliqué ... que pensez-vous de ma réponse? stackoverflow.com/questions/7902213/… . par la façon dont vous avez une erreur de copier-coller dans setContentB, vous avez écrit contentAData. remercier!
gdoron soutient Monica
1
@gdoron Croyez-moi, gérer des cours JS et envisager la séparation est une bouée de sauvetage lorsque vous avez un énorme projet
Abdul Munim
2

J'enveloppe généralement JS ayant besoin d'accéder aux propriétés du modèle, dans les fonctions, puis je passe le @ quelque chose dans la vue. Par exemple

<script type="text/javascript">
function MyFunction(somethingPresentInTheView) {
  alert(somethingPresentInTheView);
}
</script>

dans la vue, j'ajoute l'invocation de fonction via (juste un exemple):

<input type='button' onclick="MyFunction('@Model.PropertyNeeded')" />
BigMike
la source
1

Je pense que vous êtes obligé de mettre ce code JS dans la vue. L'analyseur Razor, pour autant que je sache, ne regardera pas les fichiers .js, donc tout ce que vous avez qui utilise @ne fonctionnera pas. PLus, comme vous l'avez remarqué, Javascript lui-même n'aime pas ce @caractère traîner sans raison, à part, disons, dans une chaîne.

Jason Evans
la source