简体   繁体   English

如何刷新角度标签

[英]How to refresh an angular tag

I was brought in to fix a website that was on fire a couple months back. 我被带去修复一个在几个月前着火的网站。 I've got most things under control and I'm down to fixing various wish-list items. 我已经掌握了大部分东西,现在只能解决各种愿望清单项目。 One of them involved some angular code that I just can't seem to get to do what I want. 其中之一涉及一些角度代码,我似乎无法做到自己想要的。 On some pages there are videos followed by a short quiz. 在某些页面上,有视频,然后进行简短测验。 I need to update the user's scores after each event. 每次活动后,我都需要更新用户的分数。 So far, this proved to be easy enough for the total score which looked like this: 到目前为止,事实证明,这对于看起来像这样的总分数很容易:

 <a id="updateafterscore" href="~/user/leaderboard/" class="fill-div">
                                {{ profile.currentScore }}
                            </a>

And that got updated with this: 并对此进行了更新:

document.getElementById('updateafterscore').innerHTML = data.Data.CurrentScore;

So far, so good. 到现在为止还挺好。 However other elements on the page have, thus far, proved impossible to update. 但是,到目前为止,该页面上的其他元素已被证明无法更新。 Here's what's on the page: 这是页面上的内容:

I added the "id="refreshvideo" myself so I could try to alter the tag. Finally, here's the angular module for simple-circle (I've left out the actual drawing code since it's not really relevant): 我自己添加了“ id =“ refreshvideo”,以便尝试更改标签。最后,这是简单圆的角度模块(由于与实际无关,因此省略了实际的绘图代码):

angular.module('thrive.shared').directive('simpleCircle', function() {

return{
    replace: true,
    template: '<canvas width="60" height="60" style="margin: -10px 0 0 -15px;"></canvas>',
    restrict: 'E',
    scope: {
        value: '@',
        color: '@',
        bgColor: '@',
        forecolor: '@',
        radius: '@'
    },
    link: function (scope, elem, attrs) {

        var multiplyLength = 1;
        var canvasElem = elem[0];
        var inMotion = false;

        if (scope.value <= 2) {
            multiplyLength = 5;
        }

        scope.$watch('value', function() {
            drawCircle(canvasElem, scope.color, scope.value * multiplyLength, scope.value, scope.name);
        });


        function drawCircle(canvas, color, calculatedPoints, displayPoints, name) {

So, to the question: how the heck do I update the number that's displayed? 那么,问题来了:我该如何更新显示的数字? I tried various things: 我尝试了各种方法:

document.getElementById('refreshvideo').setAttribute('value', data.Data.VideoWatchedCount);
document.getElementById('refreshvideo').setAttribute('data-value', data.Data.VideoWatchedCount);
$scope.profile.videosWatched = data.Data.VideoWatchedCount;

None of these things worked. 这些都不起作用。 I inspected the canvas element in the source in the browser and I could see the value and data-value tags change to whatever I set them, but the image remained unchanged. 我在浏览器中检查了源代码中的canvas元素,可以看到valuedata-value标签更改为我设置的内容,但是图像保持不变。 Am I setting the wrong thing? 我设置错了吗? (Perhaps whatever $watch is watching) Do I have to force some kind of re-paint of a canvas element? (也许$ watch正在观看)我是否必须强制对canvas元素进行某种重绘

@charlietfl means your solution is not actually using AngularJS - you're completely bypassing it. @charlietfl表示您的解决方案实际上并未使用AngularJS-您已完全绕开了它。 Angular provides two-way data binding between Javascript data and the HTML DOM. Angular在Javascript数据和HTML DOM之间提供了双向数据绑定。 All you do is tell it where to draw data, and it will do that for you automatically, keeping it up to date from then on as the data changes. 您所要做的就是告诉它在哪里绘制数据,它将自动为您完成操作,并从那时起保持数据更新。

In Angular, you never call getElementById and certain never set innerHTML because then you block Angular from doing its thing - in many cases you actually break it. 在Angular中,您永远不会调用getElementById,并且一定不要设置innerHTML,因为这会阻止Angular执行其操作-在许多情况下,您实际上是在破坏它。 Every one of those instances introduces a new bug while "patching" another. 这些实例中的每个实例都会在“修补”另一个实例时引入一个新的错误。

Go back to your example template line: 返回您的示例模板行:

<a ..attributes...>{{ profile.currentScore }}</a>

When it sees this, Angular will create what it calls a "watcher" on profile.currentScore. 看到此消息后,Angular将在profile.currentScore上创建所谓的“观察者”。 If its value right now is '1', it will render this as <a ...>1</a> . 如果现在它的值为'1',它将把它呈现为<a ...>1</a>

Every digest cycle, that watcher will tell it to look at profile.currentScore to see if it changed. 在每个摘要周期,该观察者将告诉它查看profile.currentScore以查看其是否更改。 This line of code is pretty typical in JS: 这行代码在JS中非常典型:

profile.currentScore = 42;

Angular will "see" this happen through that watcher, and will automatically update the rendered template. Angular将通过该观察器“看到”这种情况,并将自动更新渲染的模板。 You do nothing else - and if you ever feel that you need to, it almost always means something else is wrong. 您什么都不做-如果您觉得自己有需要,那几乎总是意味着其他事情是错的。

If you're running into this a lot, try the "standard quick-fix". 如果您经常遇到这种情况,请尝试“标准快速修复”。 We see this a lot with people who didn't architect an application properly, and they're doing data model updates outside Angular's digest cycle where it can't "see" them. 我们在没有适当地构建应用程序的人们中看到了很多,他们正在Angular的摘要周期之外进行数据模型更新,从而无法“看到”它们。 Try wrapping your update code in an $apply() call: 尝试将更新代码包装在$ apply()调用中:

$scope.$apply(function() {
    profile.currentScore = 42;
});

If you have a LOT of updates to make and you don't want to nest the call, you can also cheat, like this: 如果您要进行大量更新而又不想嵌套通话,则也可以作弊,如下所示:

// Lots of stuff...
profile.currentScore = 42;
// Lots more stuff...

$scope.$apply();

You will know right away if you need to do this. 您将立即知道是否需要执行此操作。 If it works, you need to do it. 如果有效,则需要这样做。 :) If you get an error message in your console saying you're already in a digest cycle, you do NOT need to do it (it's something else). :)如果您在控制台中收到一条错误消息,表明您已经处于摘要周期,则无需执行此操作(这是其他操作)。

I mentioned that I thought perhaps I was modifying the wrong profile variable and so it wasn't refreshing. 我提到我以为我可能是在修改错误的配置文件变量,所以它没有刷新。 So I looked back a little bit in the code that is supplying the numbers: 因此,我回顾了提供数字的代码:

angular.module('episodes').controller('episodeCtrl', ['$scope', '$rootScope', '$window', 'episode', 'relatedCourses', 'Video', 'episodeItems', 'profile', 'Profile',
function ($scope, $rootScope, $window, episode, relatedCourses, Video, episodeItems, profile, Profile) {
// stuff skipped....
                        onComplete: function () {
                            Video.complete({ videoId: item.item.id }).$promise.then(function () {
                                item.progress = "Completed";
                                $scope.loadNextItem();
                                $scope.profile = Profile.get();   // <<-- gotten from somewhere

                                $.ajaxSetup({ cache: false });
                                $.get('/user/getCurrentUserPointsModel', function (data) {
                                    if (data == "")
                                        return;
                                    $scope.profile.currentScore = data.Data.CurrentScore;
                                    $scope.profile.videosWatched = data.Data.VideoWatchedCount;
                                    $scope.profile.testTakenAndCorrectAnswerCount = data.Data.TestTakenAndCorrectAnswerCount;
                                    Profile.save();    // <-- added

The value in $scope.profile is pulled from Profile , but I don't fully get how that gets where it is. $ scope.profile中的值是从Profile提取的,但是我还没有完全了解它的位置。 I suppose I will need to figure that out because there's another place where these updates have to happen that lack that Profile information. 我想我需要弄清楚这一点,因为在另一个必须进行这些更新的地方缺少Profile信息。 Anyways I added the last 4 lines in place of this: 无论如何,我添加了最后4行来代替:

document.getElementById('updateafterscore').innerHTML = data.Data.CurrentScore;

... and all worked according to plan. ...一切都按计划进行。 I guess I tackle the other part later when I figure out how the data gets to the controller. 当我弄清楚数据如何到达控制器时,我想稍后再讨论另一部分。

You can't do this that way. 你不能那样做。 It's not Angular way of dealing with data. 这不是Angular处理数据的方式。 Read the documentation before https://docs.angularjs.org/tutorial/step_04 If you need to modify your DOM using document.. probably sth wrong is with your code. 如果需要使用文档修改DOM,请先阅读https://docs.angularjs.org/tutorial/step_04上的文档。.可能是您的代码有误。

BTW. 顺便说一句。 Stop using globals like: 停止使用全局变量,例如:

document.getElementById('updateafterscore')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM